Merge "Abstract Hard-Coded URLs to Config File"
[pharos-tools.git] / dashboard / src / account / views.py
1 ##############################################################################
2 # Copyright (c) 2016 Max Breitenfeldt and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10
11 import os
12 import urllib
13
14 import oauth2 as oauth
15 from django.conf import settings
16 from django.contrib import messages
17 from django.contrib.auth import logout, authenticate, login
18 from django.contrib.auth.decorators import login_required
19 from django.contrib.auth.mixins import LoginRequiredMixin
20 from django.contrib.auth.models import User
21 from django.urls import reverse
22 from django.utils.decorators import method_decorator
23 from django.views.generic import RedirectView, TemplateView, UpdateView
24 from jira import JIRA
25 from rest_framework.authtoken.models import Token
26
27 from account.forms import AccountSettingsForm
28 from account.jira_util import SignatureMethod_RSA_SHA1
29 from account.models import UserProfile
30
31
32 @method_decorator(login_required, name='dispatch')
33 class AccountSettingsView(UpdateView):
34     model = UserProfile
35     form_class = AccountSettingsForm
36     template_name_suffix = '_update_form'
37
38     def get_success_url(self):
39         messages.add_message(self.request, messages.INFO,
40                              'Settings saved')
41         return '/'
42
43     def get_object(self, queryset=None):
44         return self.request.user.userprofile
45
46     def get_context_data(self, **kwargs):
47         token, created = Token.objects.get_or_create(user=self.request.user)
48         context = super(AccountSettingsView, self).get_context_data(**kwargs)
49         context.update({'title': "Settings", 'token': token})
50         return context
51
52
53 class JiraLoginView(RedirectView):
54     def get_redirect_url(self, *args, **kwargs):
55         consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
56         client = oauth.Client(consumer)
57         client.set_signature_method(SignatureMethod_RSA_SHA1())
58
59         # Step 1. Get a request token from Jira.
60         try:
61             resp, content = client.request(settings.OAUTH_REQUEST_TOKEN_URL, "POST")
62         except Exception as e:
63             messages.add_message(self.request, messages.ERROR,
64                                  'Error: Connection to Jira failed. Please contact an Administrator')
65             return '/'
66         if resp['status'] != '200':
67             messages.add_message(self.request, messages.ERROR,
68                                  'Error: Connection to Jira failed. Please contact an Administrator')
69             return '/'
70
71         # Step 2. Store the request token in a session for later use.
72         self.request.session['request_token'] = dict(urllib.parse.parse_qsl(content.decode()))
73         # Step 3. Redirect the user to the authentication URL.
74         url = settings.OAUTH_AUTHORIZE_URL + '?oauth_token=' + \
75               self.request.session['request_token']['oauth_token'] + \
76               '&oauth_callback=' + settings.OAUTH_CALLBACK_URL
77         return url
78
79
80 class JiraLogoutView(LoginRequiredMixin, RedirectView):
81     def get_redirect_url(self, *args, **kwargs):
82         logout(self.request)
83         return '/'
84
85
86 class JiraAuthenticatedView(RedirectView):
87     def get_redirect_url(self, *args, **kwargs):
88         # Step 1. Use the request token in the session to build a new client.
89         consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
90         token = oauth.Token(self.request.session['request_token']['oauth_token'],
91                             self.request.session['request_token']['oauth_token_secret'])
92         client = oauth.Client(consumer, token)
93         client.set_signature_method(SignatureMethod_RSA_SHA1())
94
95         # Step 2. Request the authorized access token from Jira.
96         try:
97             resp, content = client.request(settings.OAUTH_ACCESS_TOKEN_URL, "POST")
98         except Exception as e:
99             messages.add_message(self.request, messages.ERROR,
100                                  'Error: Connection to Jira failed. Please contact an Administrator')
101             return '/'
102         if resp['status'] != '200':
103             messages.add_message(self.request, messages.ERROR,
104                                  'Error: Connection to Jira failed. Please contact an Administrator')
105             return '/'
106
107         access_token = dict(urllib.parse.parse_qsl(content.decode()))
108
109         module_dir = os.path.dirname(__file__)  # get current directory
110         with open(module_dir + '/rsa.pem', 'r') as f:
111             key_cert = f.read()
112
113         oauth_dict = {
114             'access_token': access_token['oauth_token'],
115             'access_token_secret': access_token['oauth_token_secret'],
116             'consumer_key': settings.OAUTH_CONSUMER_KEY,
117             'key_cert': key_cert
118         }
119
120         jira = JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
121         username = jira.current_user()
122         url = '/'
123         # Step 3. Lookup the user or create them if they don't exist.
124         try:
125             user = User.objects.get(username=username)
126         except User.DoesNotExist:
127             # Save our permanent token and secret for later.
128             user = User.objects.create_user(username=username,
129                                             password=access_token['oauth_token_secret'])
130             profile = UserProfile()
131             profile.user = user
132             profile.save()
133             url = reverse('account:settings')
134         user.userprofile.oauth_token = access_token['oauth_token']
135         user.userprofile.oauth_secret = access_token['oauth_token_secret']
136         user.userprofile.save()
137         user.set_password(access_token['oauth_token_secret'])
138         user.save()
139         user = authenticate(username=username, password=access_token['oauth_token_secret'])
140         login(self.request, user)
141         # redirect user to settings page to complete profile
142         return url
143
144
145 @method_decorator(login_required, name='dispatch')
146 class UserListView(TemplateView):
147     template_name = "account/user_list.html"
148
149     def get_context_data(self, **kwargs):
150         users = User.objects.all()
151         context = super(UserListView, self).get_context_data(**kwargs)
152         context.update({'title': "Dashboard Users", 'users': users})
153         return context