09c52665416f7925265374cf7610eddec6277b08
[pharos-tools.git] / dashboard / src / account / views.py
1 ##############################################################################
2 # Copyright (c) 2016 Max Breitenfeldt and others.
3 # Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10
11
12 import os
13 import urllib
14
15 import oauth2 as oauth
16 from django.conf import settings
17 from django.contrib import messages
18 from django.contrib.auth import logout, authenticate, login
19 from django.contrib.auth.decorators import login_required
20 from django.contrib.auth.mixins import LoginRequiredMixin
21 from django.contrib.auth.models import User
22 from django.urls import reverse
23 from django.utils.decorators import method_decorator
24 from django.views.generic import RedirectView, TemplateView, UpdateView
25 from django.shortcuts import render
26 from jira import JIRA
27 from rest_framework.authtoken.models import Token
28
29 from account.forms import AccountSettingsForm
30 from account.jira_util import SignatureMethod_RSA_SHA1
31 from account.models import UserProfile
32 from booking.models import Booking
33 from resource_inventory.models import GenericResourceBundle, ConfigBundle, Image
34
35
36 @method_decorator(login_required, name='dispatch')
37 class AccountSettingsView(UpdateView):
38     model = UserProfile
39     form_class = AccountSettingsForm
40     template_name_suffix = '_update_form'
41
42     def get_success_url(self):
43         messages.add_message(self.request, messages.INFO,
44                              'Settings saved')
45         return '/'
46
47     def get_object(self, queryset=None):
48         return self.request.user.userprofile
49
50     def get_context_data(self, **kwargs):
51         token, created = Token.objects.get_or_create(user=self.request.user)
52         context = super(AccountSettingsView, self).get_context_data(**kwargs)
53         context.update({'title': "Settings", 'token': token})
54         return context
55
56
57 class JiraLoginView(RedirectView):
58     def get_redirect_url(self, *args, **kwargs):
59         consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
60         client = oauth.Client(consumer)
61         client.set_signature_method(SignatureMethod_RSA_SHA1())
62
63         # Step 1. Get a request token from Jira.
64         try:
65             resp, content = client.request(settings.OAUTH_REQUEST_TOKEN_URL, "POST")
66         except Exception:
67             messages.add_message(self.request, messages.ERROR,
68                                  'Error: Connection to Jira failed. Please contact an Administrator')
69             return '/'
70         if resp['status'] != '200':
71             messages.add_message(self.request, messages.ERROR,
72                                  'Error: Connection to Jira failed. Please contact an Administrator')
73             return '/'
74
75         # Step 2. Store the request token in a session for later use.
76         self.request.session['request_token'] = dict(urllib.parse.parse_qsl(content.decode()))
77         # Step 3. Redirect the user to the authentication URL.
78         url = settings.OAUTH_AUTHORIZE_URL + '?oauth_token=' + \
79             self.request.session['request_token']['oauth_token'] + \
80             '&oauth_callback=' + settings.OAUTH_CALLBACK_URL
81         return url
82
83
84 class JiraLogoutView(LoginRequiredMixin, RedirectView):
85     def get_redirect_url(self, *args, **kwargs):
86         logout(self.request)
87         return '/'
88
89
90 class JiraAuthenticatedView(RedirectView):
91     def get_redirect_url(self, *args, **kwargs):
92         # Step 1. Use the request token in the session to build a new client.
93         consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
94         token = oauth.Token(self.request.session['request_token']['oauth_token'],
95                             self.request.session['request_token']['oauth_token_secret'])
96         client = oauth.Client(consumer, token)
97         client.set_signature_method(SignatureMethod_RSA_SHA1())
98
99         # Step 2. Request the authorized access token from Jira.
100         try:
101             resp, content = client.request(settings.OAUTH_ACCESS_TOKEN_URL, "POST")
102         except Exception:
103             messages.add_message(self.request, messages.ERROR,
104                                  'Error: Connection to Jira failed. Please contact an Administrator')
105             return '/'
106         if resp['status'] != '200':
107             messages.add_message(self.request, messages.ERROR,
108                                  'Error: Connection to Jira failed. Please contact an Administrator')
109             return '/'
110
111         access_token = dict(urllib.parse.parse_qsl(content.decode()))
112
113         module_dir = os.path.dirname(__file__)  # get current directory
114         with open(module_dir + '/rsa.pem', 'r') as f:
115             key_cert = f.read()
116
117         oauth_dict = {
118             'access_token': access_token['oauth_token'],
119             'access_token_secret': access_token['oauth_token_secret'],
120             'consumer_key': settings.OAUTH_CONSUMER_KEY,
121             'key_cert': key_cert
122         }
123
124         jira = JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
125         username = jira.current_user()
126         email = jira.user(username).emailAddress
127         url = '/'
128         # Step 3. Lookup the user or create them if they don't exist.
129         try:
130             user = User.objects.get(username=username)
131         except User.DoesNotExist:
132             # Save our permanent token and secret for later.
133             user = User.objects.create_user(username=username,
134                                             password=access_token['oauth_token_secret'])
135             profile = UserProfile()
136             profile.user = user
137             profile.save()
138             user.userprofile.email_addr = email
139             url = reverse('account:settings')
140         user.userprofile.oauth_token = access_token['oauth_token']
141         user.userprofile.oauth_secret = access_token['oauth_token_secret']
142         user.userprofile.save()
143         user.set_password(access_token['oauth_token_secret'])
144         user.save()
145         user = authenticate(username=username, password=access_token['oauth_token_secret'])
146         login(self.request, user)
147         # redirect user to settings page to complete profile
148         return url
149
150
151 @method_decorator(login_required, name='dispatch')
152 class UserListView(TemplateView):
153     template_name = "account/user_list.html"
154
155     def get_context_data(self, **kwargs):
156         users = User.objects.all()
157         context = super(UserListView, self).get_context_data(**kwargs)
158         context.update({'title': "Dashboard Users", 'users': users})
159         return context
160
161
162 def account_detail_view(request):
163     template = "account/details.html"
164     return render(request, template)
165
166
167 def account_resource_view(request):
168     """
169     gathers a users genericResoureBundles and
170     turns them into displayable objects
171     """
172     if not request.user.is_authenticated:
173         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
174     template = "account/resource_list.html"
175     resources = list(GenericResourceBundle.objects.filter(owner=request.user))
176     context = {"resources": resources, "title": "My Resources"}
177     return render(request, template, context=context)
178
179
180 def account_booking_view(request):
181     if not request.user.is_authenticated:
182         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
183     template = "account/booking_list.html"
184     bookings = list(Booking.objects.filter(owner=request.user))
185     collab_bookings = list(request.user.collaborators.all())
186     context = {"title": "My Bookings", "bookings": bookings, "collab_bookings": collab_bookings}
187     return render(request, template, context=context)
188
189
190 def account_configuration_view(request):
191     if not request.user.is_authenticated:
192         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
193     template = "account/configuration_list.html"
194     configs = list(ConfigBundle.objects.filter(owner=request.user))
195     context = {"title": "Configuration List", "configurations": configs}
196     return render(request, template, context=context)
197
198
199 def account_images_view(request):
200     if not request.user.is_authenticated:
201         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
202     template = "account/image_list.html"
203     my_images = Image.objects.filter(owner=request.user)
204     public_images = Image.objects.filter(public=True)
205     context = {"title": "Images", "images": my_images, "public_images": public_images}
206     return render(request, template, context=context)