david / django-roa (http://welldev.org/)
Turn your models into remote resources that you can access through Django's ORM. ROA stands for Resource Oriented Architecture.
| commit 121: | b9938bcba573 |
| parent 120: | 668d9e16c459 |
| branch: | default |
12 months ago
Changed (Δ5.9 KB):
piston/fixtures/models.json (46 lines added, 0 lines removed)
piston/fixtures/oauth.json (27 lines added, 0 lines removed)
piston/signals.py (14 lines added, 0 lines removed)
piston/test.py (62 lines added, 0 lines removed)
piston/tests.py (44 lines added, 0 lines removed)
Up to file-list piston/fixtures/models.json:
1 |
[ |
|
2 |
{ |
|
3 |
"pk": 2, |
|
4 |
"model": "auth.user", |
|
5 |
"fields": { |
|
6 |
"username": "pistontestuser", |
|
7 |
"first_name": "Piston", |
|
8 |
"last_name": "User", |
|
9 |
"is_active": true, |
|
10 |
"is_superuser": false, |
|
11 |
"is_staff": false, |
|
12 |
"last_login": "2009-08-03 13:11:53", |
|
13 |
"groups": [], |
|
14 |
"user_permissions": [], |
|
15 |
"password": "sha1$b6c1f$83d5879f3854f6e9d27f393e3bcb4b8db05cf671", |
|
16 |
"email": "pistontestuser@example.com", |
|
17 |
"date_joined": "2009-08-03 13:11:53" |
|
18 |
} |
|
19 |
}, |
|
20 |
{ |
|
21 |
"pk": 3, |
|
22 |
"model": "auth.user", |
|
23 |
"fields": { |
|
24 |
"username": "pistontestconsumer", |
|
25 |
"first_name": "Piston", |
|
26 |
"last_name": "Consumer", |
|
27 |
"is_active": true, |
|
28 |
"is_superuser": false, |
|
29 |
"is_staff": false, |
|
30 |
"last_login": "2009-08-03 13:11:53", |
|
31 |
"groups": [], |
|
32 |
"user_permissions": [], |
|
33 |
"password": "sha1$b6c1f$83d5879f3854f6e9d27f393e3bcb4b8db05cf671", |
|
34 |
"email": "pistontestconsumer@example.com", |
|
35 |
"date_joined": "2009-08-03 13:11:53" |
|
36 |
} |
|
37 |
}, |
|
38 |
{ |
|
39 |
"pk": 1, |
|
40 |
"model": "sites.site", |
|
41 |
"fields": { |
|
42 |
"domain": "example.com", |
|
43 |
"name": "example.com" |
|
44 |
} |
|
45 |
} |
|
46 |
] |
Up to file-list piston/fixtures/oauth.json:
1 |
[ |
|
2 |
{ |
|
3 |
"pk": 1, |
|
4 |
"model": "piston.consumer", |
|
5 |
"fields": { |
|
6 |
"status": "accepted", |
|
7 |
"name": "Piston Test Consumer", |
|
8 |
"secret": "T5XkNMkcjffDpC9mNQJbyQnJXGsenYbz", |
|
9 |
"user": 2, |
|
10 |
"key": "8aZSFj3W54h8J8sCpx", |
|
11 |
"description": "A test consumer record for Piston unit tests." |
|
12 |
} |
|
13 |
}, |
|
14 |
{ |
|
15 |
"pk": 1, |
|
16 |
"model": "piston.token", |
|
17 |
"fields": { |
|
18 |
"is_approved": true, |
|
19 |
"timestamp": 1249347414, |
|
20 |
"token_type": 2, |
|
21 |
"secret": "qSWZq36t7yvkBquetYBkd8JxnuCu9jKk", |
|
22 |
"user": 2, |
|
23 |
"key": "Y7358vL5hDBbeP3HHL", |
|
24 |
"consumer": 1 |
|
25 |
} |
|
26 |
} |
|
27 |
] |
Up to file-list piston/signals.py:
1 |
# Django imports |
|
2 |
import django.dispatch |
|
3 |
||
4 |
# Piston imports |
|
5 |
from utils import send_consumer_mail |
|
6 |
||
7 |
def consumer_post_save(sender, instance, created, **kwargs): |
|
8 |
send_consumer_mail(instance) |
|
9 |
||
10 |
def consumer_post_delete(sender, instance, **kwargs): |
|
11 |
instance.status = 'canceled' |
|
12 |
send_consumer_mail(instance) |
|
13 |
||
14 |
Up to file-list piston/test.py:
1 |
# Django imports |
|
2 |
import django.test.client as client |
|
3 |
import django.test as test |
|
4 |
from django.utils.http import urlencode |
|
5 |
||
6 |
# Piston imports |
|
7 |
from piston import oauth |
|
8 |
from piston.models import Consumer, Token |
|
9 |
||
10 |
# 3rd/Python party imports |
|
11 |
import httplib2, urllib, cgi |
|
12 |
||
13 |
URLENCODED_FORM_CONTENT = 'application/x-www-form-urlencoded' |
|
14 |
||
15 |
class OAuthClient(client.Client): |
|
16 |
def __init__(self, consumer, token): |
|
17 |
self.token = oauth.OAuthToken(token.key, token.secret) |
|
18 |
self.consumer = oauth.OAuthConsumer(consumer.key, consumer.secret) |
|
19 |
self.signature = oauth.OAuthSignatureMethod_HMAC_SHA1() |
|
20 |
||
21 |
super(OAuthClient, self).__init__() |
|
22 |
||
23 |
def request(self, **request): |
|
24 |
# Figure out parameters from request['QUERY_STRING'] and FakePayload |
|
25 |
params = {} |
|
26 |
if request['REQUEST_METHOD'] in ('POST', 'PUT'): |
|
27 |
if request['CONTENT_TYPE'] == URLENCODED_FORM_CONTENT: |
|
28 |
payload = request['wsgi.input'].read() |
|
29 |
request['wsgi.input'] = client.FakePayload(payload) |
|
30 |
params = cgi.parse_qs(payload) |
|
31 |
||
32 |
url = "http://testserver" + request['PATH_INFO'] |
|
33 |
||
34 |
req = oauth.OAuthRequest.from_consumer_and_token( |
|
35 |
self.consumer, token=self.token, |
|
36 |
http_method=request['REQUEST_METHOD'], http_url=url, |
|
37 |
parameters=params |
|
38 |
) |
|
39 |
||
40 |
req.sign_request(self.signature, self.consumer, self.token) |
|
41 |
headers = req.to_header() |
|
42 |
request['HTTP_AUTHORIZATION'] = headers['Authorization'] |
|
43 |
||
44 |
return super(OAuthClient, self).request(**request) |
|
45 |
||
46 |
def post(self, path, data={}, content_type=None, follow=False, **extra): |
|
47 |
if content_type is None: |
|
48 |
content_type = URLENCODED_FORM_CONTENT |
|
49 |
||
50 |
if isinstance(data, dict): |
|
51 |
data = urlencode(data) |
|
52 |
||
53 |
return super(OAuthClient, self).post(path, data, content_type, follow, **extra) |
|
54 |
||
55 |
class TestCase(test.TestCase): |
|
56 |
pass |
|
57 |
||
58 |
class OAuthTestCase(TestCase): |
|
59 |
@property |
|
60 |
def oauth(self): |
|
61 |
return OAuthClient(self.consumer, self.token) |
|
62 |
Up to file-list piston/tests.py:
1 |
# Django imports |
|
2 |
from django.core import mail |
|
3 |
from django.contrib.auth.models import User |
|
4 |
from django.conf import settings |
|
5 |
||
6 |
# Piston imports |
|
7 |
from test import TestCase |
|
8 |
from models import Consumer |
|
9 |
||
10 |
class ConsumerTest(TestCase): |
|
11 |
fixtures = ['models.json'] |
|
12 |
||
13 |
def setUp(self): |
|
14 |
self.consumer = Consumer() |
|
15 |
self.consumer.name = "Piston Test Consumer" |
|
16 |
self.consumer.description = "A test consumer for Piston." |
|
17 |
self.consumer.user = User.objects.get(pk=3) |
|
18 |
self.consumer.generate_random_codes() |
|
19 |
||
20 |
def test_create_pending(self): |
|
21 |
""" Ensure creating a pending Consumer sends proper emails """ |
|
22 |
# If it's pending we should have two messages in the outbox; one |
|
23 |
# to the consumer and one to the site admins. |
|
24 |
if len(settings.ADMINS): |
|
25 |
self.assertEquals(len(mail.outbox), 2) |
|
26 |
else: |
|
27 |
self.assertEquals(len(mail.outbox), 1) |
|
28 |
||
29 |
expected = "Your API Consumer for example.com is awaiting approval." |
|
30 |
self.assertEquals(mail.outbox[0].subject, expected) |
|
31 |
||
32 |
def test_delete_consumer(self): |
|
33 |
""" Ensure deleting a Consumer sends a cancel email """ |
|
34 |
||
35 |
# Clear out the outbox before we test for the cancel email. |
|
36 |
mail.outbox = [] |
|
37 |
||
38 |
# Delete the consumer, which should fire off the cancel email. |
|
39 |
self.consumer.delete() |
|
40 |
||
41 |
self.assertEquals(len(mail.outbox), 1) |
|
42 |
expected = "Your API Consumer for example.com has been canceled." |
|
43 |
self.assertEquals(mail.outbox[0].subject, expected) |
|
44 |
