summaryrefslogtreecommitdiffstats
path: root/jjb/conductor/conductor.yml
blob: 8a128da37ff4fe9da75d98f380930c43a1f970bd (plain)
1
2
3
4
5
6
7
8
---
- project:
    name: conductor

    project: '{name}'

    jobs:
      - '{project}-verify-basic'
01 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
##############################################################################
# Copyright (c) 2016 Max Breitenfeldt and others.
# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################


import os
import urllib

import oauth2 as oauth
from django.conf import settings
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.urls import reverse
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from django.views.generic import RedirectView, TemplateView, UpdateView
from django.shortcuts import render
from jira import JIRA
from rest_framework.authtoken.models import Token

from account.forms import AccountSettingsForm
from account.jira_util import SignatureMethod_RSA_SHA1
from account.models import UserProfile
from booking.models import Booking
from resource_inventory.models import GenericResourceBundle, ConfigBundle, Image, Host


@method_decorator(login_required, name='dispatch')
class AccountSettingsView(UpdateView):
    model = UserProfile
    form_class = AccountSettingsForm
    template_name_suffix = '_update_form'

    def get_success_url(self):
        messages.add_message(self.request, messages.INFO,
                             'Settings saved')
        return '/'

    def get_object(self, queryset=None):
        return self.request.user.userprofile

    def get_context_data(self, **kwargs):
        token, created = Token.objects.get_or_create(user=self.request.user)
        context = super(AccountSettingsView, self).get_context_data(**kwargs)
        context.update({'title': "Settings", 'token': token})
        return context


class JiraLoginView(RedirectView):
    def get_redirect_url(self, *args, **kwargs):
        consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
        client = oauth.Client(consumer)
        client.set_signature_method(SignatureMethod_RSA_SHA1())

        # Step 1. Get a request token from Jira.
        try:
            resp, content = client.request(settings.OAUTH_REQUEST_TOKEN_URL, "POST")
        except Exception:
            messages.add_message(self.request, messages.ERROR,
                                 'Error: Connection to Jira failed. Please contact an Administrator')
            return '/'
        if resp['status'] != '200':
            messages.add_message(self.request, messages.ERROR,
                                 'Error: Connection to Jira failed. Please contact an Administrator')
            return '/'

        # Step 2. Store the request token in a session for later use.
        self.request.session['request_token'] = dict(urllib.parse.parse_qsl(content.decode()))
        # Step 3. Redirect the user to the authentication URL.
        url = settings.OAUTH_AUTHORIZE_URL + '?oauth_token=' + \
            self.request.session['request_token']['oauth_token'] + \
            '&oauth_callback=' + settings.OAUTH_CALLBACK_URL
        return url


class JiraLogoutView(LoginRequiredMixin, RedirectView):
    def get_redirect_url(self, *args, **kwargs):
        logout(self.request)
        return '/'


class JiraAuthenticatedView(RedirectView):
    def get_redirect_url(self, *args, **kwargs):
        # Step 1. Use the request token in the session to build a new client.
        consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET)
        token = oauth.Token(self.request.session['request_token']['oauth_token'],
                            self.request.session['request_token']['oauth_token_secret'])
        client = oauth.Client(consumer, token)
        client.set_signature_method(SignatureMethod_RSA_SHA1())

        # Step 2. Request the authorized access token from Jira.
        try:
            resp, content = client.request(settings.OAUTH_ACCESS_TOKEN_URL, "POST")
        except Exception:
            messages.add_message(self.request, messages.ERROR,
                                 'Error: Connection to Jira failed. Please contact an Administrator')
            return '/'
        if resp['status'] != '200':
            messages.add_message(self.request, messages.ERROR,
                                 'Error: Connection to Jira failed. Please contact an Administrator')
            return '/'

        access_token = dict(urllib.parse.parse_qsl(content.decode()))

        module_dir = os.path.dirname(__file__)  # get current directory
        with open(module_dir + '/rsa.pem', 'r') as f:
            key_cert = f.read()

        oauth_dict = {
            'access_token': access_token['oauth_token'],
            'access_token_secret': access_token['oauth_token_secret'],
            'consumer_key': settings.OAUTH_CONSUMER_KEY,
            'key_cert': key_cert
        }

        jira = JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
        username = jira.current_user()
        email = jira.user(username).emailAddress
        url = '/'
        # Step 3. Lookup the user or create them if they don't exist.
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            # Save our permanent token and secret for later.
            user = User.objects.create_user(username=username,
                                            password=access_token['oauth_token_secret'])
            profile = UserProfile()
            profile.user = user
            profile.save()
            user.userprofile.email_addr = email
            url = reverse('account:settings')
        user.userprofile.oauth_token = access_token['oauth_token']
        user.userprofile.oauth_secret = access_token['oauth_token_secret']
        user.userprofile.save()
        user.set_password(access_token['oauth_token_secret'])
        user.save()
        user = authenticate(username=username, password=access_token['oauth_token_secret'])
        login(self.request, user)
        # redirect user to settings page to complete profile
        return url


@method_decorator(login_required, name='dispatch')
class UserListView(TemplateView):
    template_name = "account/user_list.html"

    def get_context_data(self, **kwargs):
        users = User.objects.all()
        context = super(UserListView, self).get_context_data(**kwargs)
        context.update({'title': "Dashboard Users", 'users': users})
        return context


def account_detail_view(request):
    template = "account/details.html"
    return render(request, template)


def account_resource_view(request):
    """
    gathers a users genericResoureBundles and
    turns them into displayable objects
    """
    if not request.user.is_authenticated:
        return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
    template = "account/resource_list.html"
    resources = GenericResourceBundle.objects.filter(
        owner=request.user).prefetch_related("configbundle_set")
    mapping = {}
    resource_list = []
    booking_mapping = {}
    for grb in resources:
        resource_list.append(grb)
        mapping[grb.id] = [{"id": x.id, "name": x.name} for x in grb.configbundle_set.all()]
        if Booking.objects.filter(resource__template=grb, end__gt=timezone.now()).exists():
            booking_mapping[grb.id] = "true"
    context = {
        "resources": resource_list,
        "grb_mapping": mapping,
        "booking_mapping": booking_mapping,
        "title": "My Resources"
    }
    return render(request, template, context=context)


def account_booking_view(request):
    if not request.user.is_authenticated:
        return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
    template = "account/booking_list.html"
    bookings = list(Booking.objects.filter(owner=request.user, end__gt=timezone.now()).order_by("-start"))
    my_old_bookings = Booking.objects.filter(owner=request.user, end__lt=timezone.now()).order_by("-start")
    collab_old_bookings = request.user.collaborators.filter(end__lt=timezone.now()).order_by("-start")
    expired_bookings = list(my_old_bookings.union(collab_old_bookings))
    collab_bookings = list(request.user.collaborators.filter(end__gt=timezone.now()).order_by("-start"))
    context = {
        "title": "My Bookings",
        "bookings": bookings,
        "collab_bookings": collab_bookings,
        "expired_bookings": expired_bookings
    }
    return render(request, template, context=context)


def account_configuration_view(request):
    if not request.user.is_authenticated:
        return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
    template = "account/configuration_list.html"
    configs = list(ConfigBundle.objects.filter(owner=request.user))
    context = {"title": "Configuration List", "configurations": configs}
    return render(request, template, context=context)


def account_images_view(request):
    if not request.user.is_authenticated:
        return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
    template = "account/image_list.html"
    my_images = Image.objects.filter(owner=request.user)
    public_images = Image.objects.filter(public=True)
    used_images = {}
    for image in my_images:
        if Host.objects.filter(booked=True, config__image=image).exists():
            used_images[image.id] = "true"
    context = {
        "title": "Images",
        "images": my_images,
        "public_images": public_images,
        "used_images": used_images
    }
    return render(request, template, context=context)


def resource_delete_view(request, resource_id=None):
    if not request.user.is_authenticated:
        return HttpResponse('no')  # 403?
    grb = get_object_or_404(GenericResourceBundle, pk=resource_id)
    if not request.user.id == grb.owner.id:
        return HttpResponse('no')  # 403?
    if Booking.objects.filter(resource__template=grb, end__gt=timezone.now()).exists():
        return HttpResponse('no')  # 403?
    grb.delete()
    return HttpResponse('')


def configuration_delete_view(request, config_id=None):
    if not request.user.is_authenticated:
        return HttpResponse('no')  # 403?
    config = get_object_or_404(ConfigBundle, pk=config_id)
    if not request.user.id == config.owner.id:
        return HttpResponse('no')  # 403?
    if Booking.objects.filter(config_bundle=config, end__gt=timezone.now()).exists():
        return HttpResponse('no')
    config.delete()
    return HttpResponse('')


def booking_cancel_view(request, booking_id=None):
    if not request.user.is_authenticated:
        return HttpResponse('no')  # 403?
    booking = get_object_or_404(Booking, pk=booking_id)
    if not request.user.id == booking.owner.id:
        return HttpResponse('no')  # 403?

    if booking.end < timezone.now():  # booking already over
        return HttpResponse('')

    booking.end = timezone.now()
    booking.save()
    return HttpResponse('')


def image_delete_view(request, image_id=None):
    if not request.user.is_authenticated:
        return HttpResponse('no')  # 403?
    image = get_object_or_404(Image, pk=image_id)
    if image.public or image.owner.id != request.user.id:
        return HttpResponse('no')  # 403?
    # check if used in booking
    if Host.objects.filter(booked=True, config__image=image).exists():
        return HttpResponse('no')  # 403?
    image.delete()
    return HttpResponse('')