diff --git a/src/newsreader/accounts/admin.py b/src/newsreader/accounts/admin.py
index 49390c7..02d372c 100644
--- a/src/newsreader/accounts/admin.py
+++ b/src/newsreader/accounts/admin.py
@@ -11,8 +11,18 @@ class UserAdminForm(UserChangeForm):
class Meta:
widgets = {
"email": forms.EmailInput(attrs={"size": "50"}),
- "reddit_access_token": forms.TextInput(attrs={"size": "90"}),
- "reddit_refresh_token": forms.TextInput(attrs={"size": "90"}),
+ "reddit_access_token": forms.PasswordInput(
+ attrs={"size": "90"}, render_value=True
+ ),
+ "reddit_refresh_token": forms.PasswordInput(
+ attrs={"size": "90"}, render_value=True
+ ),
+ "twitter_oauth_token": forms.PasswordInput(
+ attrs={"size": "90"}, render_value=True
+ ),
+ "twitter_oauth_token_secret": forms.PasswordInput(
+ attrs={"size": "90"}, render_value=True
+ ),
}
@@ -34,6 +44,10 @@ class UserAdmin(DjangoUserAdmin):
_("Reddit settings"),
{"fields": ("reddit_access_token", "reddit_refresh_token")},
),
+ (
+ _("Twitter settings"),
+ {"fields": ("twitter_oauth_token", "twitter_oauth_token_secret")},
+ ),
(
_("Permission settings"),
{"classes": ("collapse",), "fields": ("is_staff", "is_superuser")},
diff --git a/src/newsreader/accounts/templates/accounts/views/integrations.html b/src/newsreader/accounts/templates/accounts/views/integrations.html
index ce565ec..c5ebea8 100644
--- a/src/newsreader/accounts/templates/accounts/views/integrations.html
+++ b/src/newsreader/accounts/templates/accounts/views/integrations.html
@@ -44,13 +44,25 @@
Twitter
-
+ {% if twitter_request_url %}
+
+ {% else %}
+
+ {% endif %}
-
+ {% if twitter_revoke_url %}
+
+ {% else %}
+
+ {% endif %}
diff --git a/src/newsreader/accounts/urls.py b/src/newsreader/accounts/urls.py
index 68f27a6..f94f5ec 100644
--- a/src/newsreader/accounts/urls.py
+++ b/src/newsreader/accounts/urls.py
@@ -20,6 +20,8 @@ from newsreader.accounts.views import (
RegistrationCompleteView,
RegistrationView,
SettingsView,
+ TwitterAuthRedirectView,
+ TwitterTemplateView,
)
@@ -84,6 +86,16 @@ urlpatterns = [
login_required(RedditRevokeRedirectView.as_view()),
name="reddit-revoke",
),
+ path(
+ "settings/integrations/twitter/request/",
+ login_required(TwitterAuthRedirectView.as_view()),
+ name="twitter-request",
+ ),
+ path(
+ "settings/integrations/twitter/callback/",
+ login_required(TwitterTemplateView.as_view()),
+ name="twitter-template",
+ ),
path(
"settings/integrations",
login_required(IntegrationsView.as_view()),
diff --git a/src/newsreader/accounts/views/__init__.py b/src/newsreader/accounts/views/__init__.py
index 9325728..7c0b946 100644
--- a/src/newsreader/accounts/views/__init__.py
+++ b/src/newsreader/accounts/views/__init__.py
@@ -4,6 +4,8 @@ from newsreader.accounts.views.integrations import (
RedditRevokeRedirectView,
RedditTemplateView,
RedditTokenRedirectView,
+ TwitterAuthRedirectView,
+ TwitterTemplateView,
)
from newsreader.accounts.views.password import (
PasswordChangeView,
diff --git a/src/newsreader/accounts/views/integrations.py b/src/newsreader/accounts/views/integrations.py
index 3b30ba3..a8ec089 100644
--- a/src/newsreader/accounts/views/integrations.py
+++ b/src/newsreader/accounts/views/integrations.py
@@ -37,6 +37,7 @@ class IntegrationsView(TemplateView):
return {
**super().get_context_data(**kwargs),
**self.get_reddit_context(**kwargs),
+ **self.get_twitter_context(**kwargs),
}
def get_reddit_context(self, **kwargs):
@@ -66,6 +67,19 @@ class IntegrationsView(TemplateView):
),
}
+ def get_twitter_context(self, **kwargs):
+ twitter_revoke_url = None
+ user = self.request.user
+
+ # TODO add revoke url
+ if user.twitter_oauth_token and user.twitter_oauth_token_secret:
+ twitter_revoke_url = "https://foo/bar"
+
+ return {
+ "twitter_request_url": reverse_lazy("accounts:twitter-request"),
+ "twitter_revoke_url": twitter_revoke_url,
+ }
+
class RedditTemplateView(TemplateView):
template_name = "accounts/views/reddit.html"
@@ -162,8 +176,6 @@ class RedditRevokeRedirectView(RedirectView):
return response
-# TODO hookup url to urlconf
-# TODO hookup url to integrations button
class TwitterAuthRedirectView(RedirectView):
url = reverse_lazy("accounts:integrations")
@@ -182,8 +194,7 @@ class TwitterAuthRedirectView(RedirectView):
messages.error(request, _("Unable to retrieve initial Twitter token"))
return super().get(request, *args, **kwargs)
- params = parse_qs(response.content)
-
+ params = parse_qs(response.text)
request_oauth_token = params.get("oauth_token")[0]
request_oauth_secret = params.get("oauth_token_secret")[0]
@@ -194,20 +205,20 @@ class TwitterAuthRedirectView(RedirectView):
}
)
- request_params = urlencode({"oauth_token": request_oauth_secret})
+ request_params = urlencode({"oauth_token": request_oauth_token})
return redirect(f"{TWITTER_AUTH_URL}/?{request_params}")
-# TODO hookup url
+# TODO remove cached tokens
class TwitterTemplateView(TemplateView):
template_name = "accounts/views/twitter.html"
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
- denied = request.GET.get("denied", True)
+ denied = request.GET.get("denied", False)
oauth_token = request.GET.get("oauth_token")
- request.GET.get("oauth_verifier")
+ oauth_verifier = request.GET.get("oauth_verifier")
if denied:
return self.render_to_response(
@@ -231,7 +242,7 @@ class TwitterTemplateView(TemplateView):
cached_secret = cache.get(f"twitter-{request.user.email}-secret")
- if not cached_token or not cached_token_secret:
+ if not cached_token or not cached_secret:
return self.render_to_response(
{
**context,
@@ -245,7 +256,7 @@ class TwitterTemplateView(TemplateView):
client_secret=settings.TWITTER_CONSUMER_SECRET,
resource_owner_key=cached_token,
resource_owner_secret=cached_secret,
- verifier=oauth_token_secret,
+ verifier=oauth_verifier,
)
try:
@@ -261,7 +272,7 @@ class TwitterTemplateView(TemplateView):
}
)
- params = parse_qs(response.content)
+ params = parse_qs(response.text)
oauth_token = params.get("oauth_token")[0]
oauth_secret = params.get("oauth_token_secret")[0]