Skip to content

Commit 032cba8

Browse files
author
Marco DiDomenico
committed
debug and fix callback
1 parent 45e4460 commit 032cba8

File tree

6 files changed

+101
-72
lines changed

6 files changed

+101
-72
lines changed

README.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,37 @@ Register Your Application with Replyify
2727
Configure the django-replyify-oauth2 module
2828
-------------------------------------------
2929

30-
From your previously configured app, found at https://app.replyify.com/oauth2/applications add the following to your Django settings:
31-
* REPLYIFY_CLIENT_ID
32-
* REPLYIFY_CLIENT_SECRET
33-
* REPLYIFY_REDIRECT_URI
34-
* REPLYIFY_USER_ID_FIELD
30+
From your previously configured app, found at https://app.replyify.com/oauth2/applications add the following to your Django `settings.py`:
31+
32+
REPLYIFY_CLIENT_ID = '{ update me }'
33+
REPLYIFY_CLIENT_SECRET = '{ update me }'
34+
REPLYIFY_USER_ID_FIELD = 'id' # or other unique field like `id`
35+
36+
INSTALLED_APPS = [
37+
...
38+
'replyify_oauth2',
39+
...
40+
]
3541

3642
And add the following to your `urls.py`
3743

44+
from django.conf.urls import patterns, include, url
3845
urlpatterns = patterns(
3946
...
4047
url(r'^replyify/', include('replyify_oauth2.urls', namespace='replyify')),
4148
...
4249
)
4350

51+
Run migrate:
52+
53+
$ python manage.py migrate
54+
55+
4456
In your templates you can initiate the OAuth2 workflow like this:
4557

46-
<a href="{% url 'replyify:authorize' %}">Connect to Replyify</a>
58+
<a href="{% url 'replyify:authorize' %}?next={% url 'home'|urlencode %}">Connect to Replyify</a>
4759

60+
Note: you can pass `next` query parameter to the authorize view to direct the user to correct page after OAuth flow has completed successfully. Default will send user to '/'
4861

4962

5063

README.rst

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,38 @@ Register Your Application with Replyify
3131
Configure the django-replyify-oauth2 module
3232
-------------------------------------------
3333

34-
From your previously configured app, found at https://app.replyify.com/oauth2/applications add the following to your Django settings:
35-
- REPLYIFY_CLIENT_ID
36-
- REPLYIFY_CLIENT_SECRET
37-
- REPLYIFY_REDIRECT_URI
38-
- REPLYIFY_USER_ID_FIELD
34+
From your previously configured app, found at https://app.replyify.com/oauth2/applications add the following to your Django `settings.py`:
35+
::
36+
REPLYIFY_CLIENT_ID = '{ update me }'
37+
REPLYIFY_CLIENT_SECRET = '{ update me }'
38+
REPLYIFY_USER_ID_FIELD = 'id' # or other unique field like `id`
39+
40+
INSTALLED_APPS = [
41+
...
42+
'replyify_oauth2',
43+
...
44+
]
3945

4046
And add the following to your `urls.py`
4147
::
48+
from django.conf.urls import patterns, include, url
4249
urlpatterns = patterns(
4350
...
4451
url(r'^replyify/', include('replyify_oauth2.urls', namespace='replyify')),
4552
...
4653
)
4754

55+
Run migrate
56+
::
57+
58+
$ python manage.py migrate
59+
60+
In templates
61+
::
62+
<a href="{% url 'replyify:authorize' %}?next={% url 'home'|urlencode %}">Connect to Replyify</a>
63+
64+
Note: you can pass `next` query parameter to the authorize view to direct the user to correct page after OAuth flow has completed successfully. Default will send user to '/'
65+
4866

4967
Using the Replyify API
5068
----------------------

replyify_oauth2/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from django.contrib import admin
1010
from django.contrib.auth import get_user_model
11-
from django.conf import settings
11+
from . import settings
1212
from .models import Credentials
1313

1414

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11 on 2017-04-11 21:18
23
from __future__ import unicode_literals
34

5+
from django.conf import settings
46
from django.db import migrations, models
7+
import django.db.models.deletion
58
import django.utils.timezone
6-
from django.conf import settings
79

810

911
class Migration(migrations.Migration):
1012

13+
initial = True
14+
1115
dependencies = [
1216
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
1317
]
@@ -16,13 +20,15 @@ class Migration(migrations.Migration):
1620
migrations.CreateModel(
1721
name='Credentials',
1822
fields=[
19-
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True, related_name='replyify_credentials')),
20-
('user', models.OneToOneField(null=True, to=settings.AUTH_USER_MODEL)),
23+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
2124
('access_token', models.CharField(max_length=50)),
2225
('refresh_token', models.CharField(max_length=50)),
2326
('expires', models.DateTimeField(default=django.utils.timezone.now)),
2427
('scope', models.CharField(max_length=50)),
2528
('token_type', models.CharField(max_length=50)),
29+
('updated', models.DateTimeField(auto_now=True)),
30+
('created', models.DateTimeField(auto_now_add=True)),
31+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='replyify_credentials', to=settings.AUTH_USER_MODEL)),
2632
],
2733
),
2834
]

replyify_oauth2/views.py

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,66 +8,73 @@
88
from django.contrib.auth.decorators import login_required
99
from django.http import HttpResponse
1010
from django.shortcuts import redirect
11+
from django.contrib import messages
1112
from django.utils import timezone
12-
from django.utils.crypto import get_random_string
1313
from .models import Credentials
1414
from . import settings
1515
from datetime import timedelta
1616
import requests
17+
import urllib
18+
import logging
19+
logging.basicConfig(level=logging.INFO)
20+
logger = logging.getLogger(__name__)
1721

1822

1923
def index(request=None):
20-
return HttpResponse("Replyify-OAuth2 index.")
24+
return HttpResponse('Replyify-OAuth2 index.')
2125

2226

2327
@login_required
2428
def authorize(request=None):
25-
uid = getattr(request.user, settings.REPLYIFY_USER_ID_FIELD)
26-
client_id = settings.REPLYIFY_CLIENT_ID
27-
redirect_uri = settings.REPLYIFY_REDIRECT_URI
28-
response_type = 'code'
29-
30-
state = get_random_string(20, "abcdefghijklmnopqrstuvwxyz0123456789")
31-
request.session['state'] = {state: uid}
32-
33-
args = [
34-
"client_id={0}".format(client_id),
35-
"redirect_uri={0}".format(redirect_uri),
36-
"response_type={0}".format(response_type),
37-
"state={0}".format(state)
38-
]
39-
url = "{0}?{1}".format(settings.REPLYIFY_AUTH_URL, "&".join(args))
40-
29+
# uid = getattr(request.user, settings.REPLYIFY_USER_ID_FIELD)
30+
next_url = request.GET.get('next', request.GET.get('state', '/'))
31+
logger.info('** REPLYIFY: /authorize - Next URL: {}'.format(next_url))
32+
# state = get_random_string(20, 'abcdefghijklmnopqrstuvwxyz0123456789')
33+
request.session['state'] = next_url
34+
params = {
35+
'client_id': settings.REPLYIFY_CLIENT_ID,
36+
'redirect_uri': settings.REPLYIFY_REDIRECT_URI,
37+
'response_type': 'code',
38+
'state': next_url,
39+
}
40+
url = '{0}?{1}'.format(settings.REPLYIFY_AUTH_URL, urllib.urlencode(params))
41+
logger.info('** REPLYIFY: /authorize - Redirecting to: {}'.format(url))
4142
return redirect(url)
4243

4344

4445
@login_required
4546
def callback(request=None):
4647
if 'error' in request.GET:
4748
raise Exception(request.GET['error'])
48-
49-
uid = _check_state(request)
50-
code = request.GET['code']
49+
logger.info('** REPLYIFY: /callback')
5150
data = {
5251
'grant_type': 'authorization_code',
53-
'code': code,
52+
'code': request.GET['code'],
5453
'client_id': settings.REPLYIFY_CLIENT_ID,
54+
'client_secret': settings.REPLYIFY_CLIENT_SECRET,
5555
'redirect_uri': settings.REPLYIFY_REDIRECT_URI
5656
}
5757
url = settings.REPLYIFY_TOKEN_URL
58-
r = requests.post(url=url, data=data)
59-
data = r.json()
60-
creds = _store_credentials(uid, data)
61-
62-
return HttpResponse(creds)
58+
logger.info('** REPLYIFY: Token URL - {}'.format(url))
59+
logger.info('** REPLYIFY: Token data - {}'.format(data))
60+
response = requests.post(url=url, data=data)
61+
response_data = response.json()
62+
logger.info('** REPLYIFY: Response data - {}'.format(response_data))
63+
if response_data.get('error'):
64+
logger.error('** REPLYIFY ERROR: {}'.format(response_data['error']))
65+
messages.error(request, 'REPLYIFY ERROR: {}'.format(response_data['error']))
66+
else:
67+
_store_credentials(request.user, response_data)
68+
return redirect(request.GET.get('state', '/'))
6369

6470

6571
@login_required
6672
def refresh(request=None):
6773
if 'error' in request.GET:
6874
raise Exception(request.GET['error'])
69-
75+
logger.info('** REPLYIFY: /refresh')
7076
try:
77+
next_url = request.GET.get('next', request.GET.get('state', '/'))
7178
creds = Credentials.objects.get(user=request.user)
7279

7380
data = {
@@ -78,38 +85,23 @@ def refresh(request=None):
7885
}
7986

8087
url = settings.REPLYIFY_TOKEN_URL
81-
r = requests.post(url=url, data=data)
82-
data = r.json()
83-
84-
creds = _store_credentials(user=request.user, data=data)
85-
return HttpResponse(creds)
88+
logger.info('** REPLYIFY: Refresh Token URL - {}'.format(url))
89+
logger.info('** REPLYIFY: Token data - {}'.format(data))
90+
response = requests.post(url=url, data=data)
91+
_store_credentials(request.user, response.json())
92+
return redirect(next_url)
8693

8794
except Credentials.DoesNotExist:
8895
authorize(request)
8996

9097

91-
def _check_state(request=None):
92-
uid = getattr(request.user, settings.REPLYIFY_USER_ID_FIELD)
93-
msg = "Something fishy is happening. Abort ..."
94-
95-
if 'state' not in request.session:
96-
raise Exception(msg)
97-
state = request.GET['state']
98-
from_session = request.session['state'][state]
99-
if from_session != uid:
100-
raise Exception(msg)
101-
102-
request.session.pop('state')
103-
return uid
104-
105-
106-
def _store_credentials(user, data=None):
98+
def _store_credentials(user, replyify_json=None):
10799
assert user is not None
108100
creds, _ = Credentials.objects.get_or_create(user=user)
109-
creds.access_token = data['access_token']
110-
creds.refresh_token = data['refresh_token']
111-
creds.expires = timezone.now() + timedelta(seconds=data['expires_in'])
112-
creds.scope = data['scope']
113-
creds.token_type = data['token_type']
101+
creds.access_token = replyify_json['access_token']
102+
creds.refresh_token = replyify_json['refresh_token']
103+
creds.expires = timezone.now() + timedelta(seconds=replyify_json['expires_in'])
104+
creds.scope = replyify_json['scope']
105+
creds.token_type = replyify_json['token_type']
114106
creds.save()
115107
return creds

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
VERSION = v.read()
2121

2222

23-
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
23+
with open(os.path.join(os.path.dirname(__file__), 'README.rst'), 'r') as readme:
2424
README = readme.read()
2525

2626

@@ -42,8 +42,8 @@
4242
'replyify_oauth2.migrations',
4343
],
4444
install_requires=[
45-
'Django>=1.6'
46-
'requests>=0.8.8'
45+
'Django>=1.6',
46+
'requests>=0.8.8',
4747
],
4848
scripts=[],
4949
include_package_data=True,

0 commit comments

Comments
 (0)