Lab as a Service 2.0
[laas.git] / 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 as e:
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 as e:
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 def account_resource_view(request):
167     """
168     gathers a users genericResoureBundles and
169     turns them into displayable objects
170     """
171     if not request.user.is_authenticated:
172         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
173     template = "account/resource_list.html"
174     resources = list(GenericResourceBundle.objects.filter(owner=request.user))
175     context = {"resources": resources, "title": "My Resources"}
176     return render(request, template, context=context)
177
178 def account_booking_view(request):
179     if not request.user.is_authenticated:
180         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
181     template = "account/booking_list.html"
182     bookings = list(Booking.objects.filter(owner=request.user))
183     collab_bookings = list(request.user.collaborators.all())
184     context = {"title": "My Bookings", "bookings": bookings, "collab_bookings": collab_bookings}
185     return render(request, template, context=context)
186
187 def account_configuration_view(request):
188     if not request.user.is_authenticated:
189         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
190     template = "account/configuration_list.html"
191     configs = list(ConfigBundle.objects.filter(owner=request.user))
192     context = {"title": "Configuration List", "configurations": configs}
193     return render(request, template, context=context)
194
195 def account_images_view(request):
196     if not request.user.is_authenticated:
197         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
198     template = "account/image_list.html"
199     my_images = Image.objects.filter(owner=request.user)
200     public_images = Image.objects.filter(public=True)
201     context = {"title": "Images", "images": my_images, "public_images": public_images }
202     return render(request, template, context=context)
203