From 6c0ebb775f8034d239eefb3dd4fc148ce6558474 Mon Sep 17 00:00:00 2001 From: Joe Gregorio Date: Wed, 16 Feb 2011 16:12:46 -0500 Subject: [PATCH] Added a sample for OAuth 2.0 and Django --- samples/oauth2/django_sample/__init__.py | 0 samples/oauth2/django_sample/buzz/__init__.py | 0 samples/oauth2/django_sample/buzz/models.py | 33 +++++++ samples/oauth2/django_sample/buzz/tests.py | 24 +++++ samples/oauth2/django_sample/buzz/views.py | 64 ++++++++++++++ samples/oauth2/django_sample/manage.py | 15 ++++ samples/oauth2/django_sample/settings.py | 83 ++++++++++++++++++ samples/oauth2/django_sample/static/go.png | Bin 0 -> 1139 bytes .../django_sample/templates/buzz/login.html | 23 +++++ .../django_sample/templates/buzz/welcome.html | 33 +++++++ samples/oauth2/django_sample/urls.py | 25 ++++++ 11 files changed, 300 insertions(+) create mode 100644 samples/oauth2/django_sample/__init__.py create mode 100644 samples/oauth2/django_sample/buzz/__init__.py create mode 100644 samples/oauth2/django_sample/buzz/models.py create mode 100644 samples/oauth2/django_sample/buzz/tests.py create mode 100644 samples/oauth2/django_sample/buzz/views.py create mode 100755 samples/oauth2/django_sample/manage.py create mode 100644 samples/oauth2/django_sample/settings.py create mode 100644 samples/oauth2/django_sample/static/go.png create mode 100644 samples/oauth2/django_sample/templates/buzz/login.html create mode 100644 samples/oauth2/django_sample/templates/buzz/welcome.html create mode 100644 samples/oauth2/django_sample/urls.py diff --git a/samples/oauth2/django_sample/__init__.py b/samples/oauth2/django_sample/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/samples/oauth2/django_sample/buzz/__init__.py b/samples/oauth2/django_sample/buzz/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/samples/oauth2/django_sample/buzz/models.py b/samples/oauth2/django_sample/buzz/models.py new file mode 100644 index 0000000..69c180c --- /dev/null +++ b/samples/oauth2/django_sample/buzz/models.py @@ -0,0 +1,33 @@ +import pickle +import base64 + +from django.contrib import admin +from django.contrib.auth.models import User +from django.db import models + +from oauth2client.django_orm import FlowField +from oauth2client.django_orm import CredentialsField + +# The Flow could also be stored in memcache since it is short lived. + + +class FlowModel(models.Model): + id = models.ForeignKey(User, primary_key=True) + flow = FlowField() + + +class CredentialsModel(models.Model): + id = models.ForeignKey(User, primary_key=True) + credential = CredentialsField() + + +class CredentialsAdmin(admin.ModelAdmin): + pass + + +class FlowAdmin(admin.ModelAdmin): + pass + + +admin.site.register(CredentialsModel, CredentialsAdmin) +admin.site.register(FlowModel, FlowAdmin) diff --git a/samples/oauth2/django_sample/buzz/tests.py b/samples/oauth2/django_sample/buzz/tests.py new file mode 100644 index 0000000..927cadf --- /dev/null +++ b/samples/oauth2/django_sample/buzz/tests.py @@ -0,0 +1,24 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} diff --git a/samples/oauth2/django_sample/buzz/views.py b/samples/oauth2/django_sample/buzz/views.py new file mode 100644 index 0000000..b59a334 --- /dev/null +++ b/samples/oauth2/django_sample/buzz/views.py @@ -0,0 +1,64 @@ +import os +import logging +import httplib2 + +from django.http import HttpResponse +from django.core.urlresolvers import reverse +from django.contrib.auth.decorators import login_required + +from oauth2client.django_orm import Storage +from oauth2client.client import OAuth2WebServerFlow +from django_sample.buzz.models import CredentialsModel +from django_sample.buzz.models import FlowModel +from apiclient.discovery import build + +from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response + +STEP2_URI = 'http://gregorio2.cnc.corp.google.com:8000/auth_return' + + +@login_required +def index(request): + storage = Storage(CredentialsModel, 'id', request.user, 'credential') + credential = storage.get() + if credential is None: + flow = OAuth2WebServerFlow( + client_id='837647042410.apps.googleusercontent.com', + client_secret='+SWwMCL9d8gWtzPRa1lXw5R8', + scope='https://www.googleapis.com/auth/buzz', + user_agent='buzz-django-sample/1.0', + ) + + authorize_url = flow.step1_get_authorize_url(STEP2_URI) + f = FlowModel(id=request.user, flow=flow) + f.save() + return HttpResponseRedirect(authorize_url) + else: + http = httplib2.Http() + http = credential.authorize(http) + p = build("buzz", "v1", http=http) + activities = p.activities() + activitylist = activities.list(scope='@consumption', + userId='@me').execute() + logging.info(activitylist) + + return render_to_response('buzz/welcome.html', { + 'activitylist': activitylist, + }) + +@login_required +def auth_return(request): + try: + f = FlowModel.objects.get(id=request.user) + print f + print f.flow + print dir(f.flow) + print type(f.flow) + credential = f.flow.step2_exchange(request.REQUEST) + storage = Storage(CredentialsModel, 'id', request.user, 'credential') + storage.put(credential) + f.delete() + return HttpResponseRedirect("/") + except FlowModel.DoesNotExist: + pass diff --git a/samples/oauth2/django_sample/manage.py b/samples/oauth2/django_sample/manage.py new file mode 100755 index 0000000..0b932da --- /dev/null +++ b/samples/oauth2/django_sample/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("""Error: Can't find the file 'settings.py' in the +directory containing %r. It appears you've customized things. You'll +have to run django-admin.py, passing it your settings module. +(If the file settings.py does indeed exist, it's causing an ImportError +somehow.)\n""" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/samples/oauth2/django_sample/settings.py b/samples/oauth2/django_sample/settings.py new file mode 100644 index 0000000..565d2e5 --- /dev/null +++ b/samples/oauth2/django_sample/settings.py @@ -0,0 +1,83 @@ +# Django settings for django_sample project. +import os + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'sqlite3' +DATABASE_NAME = 'database.sqlite3' +DATABASE_USER = '' +DATABASE_PASSWORD = '' +DATABASE_HOST = '' +DATABASE_PORT = '' + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/New_York' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '_=9hq-$t_uv1ckf&s!y2$9g$1dm*6p1cl%*!^mg=7gr)!zj32d' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', +) + +ROOT_URLCONF = 'django_sample.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + os.path.join(os.path.dirname(__file__), 'templates') +) + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django_sample.buzz' +) diff --git a/samples/oauth2/django_sample/static/go.png b/samples/oauth2/django_sample/static/go.png new file mode 100644 index 0000000000000000000000000000000000000000..e5aacda8c654cc9c3349639d6975741c99a368c8 GIT binary patch literal 1139 zcmV-(1dRKMP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ige< z4j2fDH-&Qm000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000BdNkl#C^jk*3sDS21QXOkMa4jn&22wE?$zCEyk<6g>N&gTedf%WGrNo?l}e?M z#l|4Zjg>OU@0#87Z(^C8$(r9724a|!Sg)c-rkf0AU{7}(l}8Rv9q%S zj^m)$>oG7efW5sv{M7%Mv;nxgyMxc?gUx0`PEL*_pO=>xEH5vkrKJT%qY)Dm6NpBm zbOO+7wQx8b2m}JSy}iZa;v%e8D>NF7B>$_cD@;yKqPn^oR;v|DOG|iuex|bq6c-m` zXlMwbPzcx8*YJA1Fq_Sid{e0u_V@QOI5-HsUJs7ru)VzvQ55Mcf)y1N@OV53hr>8K zJHz<+I1C1ZB;Q0L0iNg4(b0j*%1Vrmj^h0MoZeR0WHMoDY6{V46bA2#8O zW3d>#UN1~06B-&CFh4&}_gSE^u@Q4~bBM)a2nK`TI8O3Ta&&Zr;o)Ir9EMnyMORlB zR#sO2Y9~?DY4E>0NhA_Mb93|ePe3LCNG6jA27?d;0h^nfNF)-<2Ox?fc6WCn2m<_m zKc1eR{_PU{DdES*#}EVoYinzW$K$em>+9=52%!(a<>e&=L4Y6#h(sc?d`nA9!Eqc2 zAuyRt^khIh9>?nHDtMm9$;pW<-@Lp$^z`(=<#M5|tqlyr(6Iy_A0M&4z7C(yhfpXa zyNzvXY62kyeSLi>EG(p>1|$**1OfpFf`F~9E!m&L3_S`I|w1NPL3G~K&p6#VbI#z3PK2adwZePYJav9{Z}ulsi}d><$}}cM0t66 z#x!5w3ZST{2o8q>gb-LP7G$EO9RSO+=Your username and password didn't match. Please try again.

+{% endif %} + +
+ + + + + + + + + +
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
+ + + +
+ +{% endblock %} diff --git a/samples/oauth2/django_sample/templates/buzz/welcome.html b/samples/oauth2/django_sample/templates/buzz/welcome.html new file mode 100644 index 0000000..07e8027 --- /dev/null +++ b/samples/oauth2/django_sample/templates/buzz/welcome.html @@ -0,0 +1,33 @@ + + + + Buzz Stuff + + + + + {% for item in activitylist.items %} + + + + + + {% endfor %} +
+ {% if item.actor.thumbnailUrl %} + + + + {% endif %} +
+ {{ item.actor.name }}
+ {{ item.object.content|safe }} + + +
+ + diff --git a/samples/oauth2/django_sample/urls.py b/samples/oauth2/django_sample/urls.py new file mode 100644 index 0000000..aeba620 --- /dev/null +++ b/samples/oauth2/django_sample/urls.py @@ -0,0 +1,25 @@ +import os +from django.conf.urls.defaults import * + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + # Example: + (r'^$', 'django_sample.buzz.views.index'), + (r'^auth_return', 'django_sample.buzz.views.auth_return'), + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^admin/', include(admin.site.urls)), + (r'^accounts/login/$', 'django.contrib.auth.views.login', + {'template_name': 'buzz/login.html'}), + + (r'^static/(?P.*)$', 'django.views.static.serve', + {'document_root': os.path.join(os.path.dirname(__file__), 'static') +}), +)