summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pharos-dashboard/account/forms.py2
-rw-r--r--pharos-dashboard/account/models.py6
-rw-r--r--pharos-dashboard/booking/models.py4
-rw-r--r--pharos-dashboard/booking/tests/test_models.py12
-rw-r--r--pharos-dashboard/booking/tests/test_views.py4
-rw-r--r--pharos-dashboard/booking/views.py44
-rw-r--r--pharos-dashboard/dashboard/fixtures/dashboard.json18
-rw-r--r--pharos-dashboard/dashboard/models.py4
-rw-r--r--pharos-dashboard/dashboard/views.py2
-rw-r--r--pharos-dashboard/jenkins/models.py3
-rw-r--r--pharos-dashboard/pharos_dashboard/settings.py2
-rw-r--r--pharos-dashboard/templates/account/userprofile_update_form.html4
-rw-r--r--pharos-dashboard/templates/booking/booking_form.html21
-rw-r--r--pharos-dashboard/templates/registration/login.html51
-rw-r--r--pharos-dashboard/templates/registration/registration_form.html30
15 files changed, 61 insertions, 146 deletions
diff --git a/pharos-dashboard/account/forms.py b/pharos-dashboard/account/forms.py
index 14f11cd..92c55d8 100644
--- a/pharos-dashboard/account/forms.py
+++ b/pharos-dashboard/account/forms.py
@@ -9,6 +9,4 @@ class AccountSettingsForm(forms.ModelForm):
model = UserProfile
fields = ['company', 'ssh_public_key', 'pgp_public_key', 'timezone']
- ssh_public_key = forms.CharField(max_length=2048, widget=forms.Textarea)
- pgp_public_key = forms.CharField(max_length=2048, widget=forms.Textarea)
timezone = forms.ChoiceField(choices=[(x, x) for x in pytz.common_timezones], initial='UTC')
diff --git a/pharos-dashboard/account/models.py b/pharos-dashboard/account/models.py
index fbabf6c..fb2c8dd 100644
--- a/pharos-dashboard/account/models.py
+++ b/pharos-dashboard/account/models.py
@@ -4,12 +4,14 @@ from django.contrib.auth.models import User
from dashboard.models import Resource
+def upload_to(object, filename):
+ return object.user.username + '/' + filename
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
timezone = models.CharField(max_length=100, blank=False, default='UTC')
- ssh_public_key = models.CharField(max_length=2048, blank=False)
- pgp_public_key = models.CharField(max_length=2048, blank=False)
+ ssh_public_key = models.FileField(upload_to=upload_to, null=True, blank=True)
+ pgp_public_key = models.FileField(upload_to=upload_to, null=True, blank=True)
company = models.CharField(max_length=200, blank=False)
oauth_token = models.CharField(max_length=1024, blank=False)
oauth_secret = models.CharField(max_length=1024, blank=False)
diff --git a/pharos-dashboard/booking/models.py b/pharos-dashboard/booking/models.py
index 719dd9b..8011fa4 100644
--- a/pharos-dashboard/booking/models.py
+++ b/pharos-dashboard/booking/models.py
@@ -10,6 +10,7 @@ class Booking(models.Model):
resource = models.ForeignKey(Resource, models.PROTECT)
start = models.DateTimeField()
end = models.DateTimeField()
+ jira_issue_id = models.IntegerField(null=True)
purpose = models.CharField(max_length=300, blank=False)
@@ -25,11 +26,10 @@ class Booking(models.Model):
if user.has_perm('booking.add_booking'):
return True
# Check if User owns this resource
- if user in self.resource.owners.all():
+ if user == self.resource.owner:
return True
return False
-
def save(self, *args, **kwargs):
"""
Save the booking if self.user is authorized and there is no overlapping booking.
diff --git a/pharos-dashboard/booking/tests/test_models.py b/pharos-dashboard/booking/tests/test_models.py
index 00f6b26..7a572c5 100644
--- a/pharos-dashboard/booking/tests/test_models.py
+++ b/pharos-dashboard/booking/tests/test_models.py
@@ -4,6 +4,7 @@ from django.contrib.auth.models import User, Permission
from django.test import TestCase
from django.utils import timezone
+from account.models import UserProfile
from booking.models import Booking
from dashboard.models import Resource
from jenkins.models import JenkinsSlave
@@ -12,9 +13,12 @@ from jenkins.models import JenkinsSlave
class BookingModelTestCase(TestCase):
def setUp(self):
self.slave = JenkinsSlave.objects.create(name='test', url='test')
+ self.owner = User.objects.create(username='owner')
- self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', url='x')
- self.res2 = Resource.objects.create(name='res2', slave=self.slave, description='x', url='x')
+ self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x',
+ url='x',owner=self.owner)
+ self.res2 = Resource.objects.create(name='res2', slave=self.slave, description='x',
+ url='x',owner=self.owner)
self.user1 = User.objects.create(username='user1')
@@ -78,12 +82,14 @@ class BookingModelTestCase(TestCase):
def test_authorization(self):
user = User.objects.create(username='user')
+ user.userprofile = UserProfile.objects.create(user=user)
self.assertRaises(PermissionError, Booking.objects.create, start=timezone.now(),
end=timezone.now() + timedelta(days=1), resource=self.res1, user=user)
- self.res1.owners.add(user)
+ self.res1.owner = user
self.assertTrue(
Booking.objects.create(start=timezone.now(), end=timezone.now() + timedelta(days=1),
resource=self.res1, user=user))
+ self.res1.owner = self.owner
user.user_permissions.add(self.add_booking_perm)
user = User.objects.get(pk=user.id)
self.assertTrue(
diff --git a/pharos-dashboard/booking/tests/test_views.py b/pharos-dashboard/booking/tests/test_views.py
index b0c4b49..c5dff58 100644
--- a/pharos-dashboard/booking/tests/test_views.py
+++ b/pharos-dashboard/booking/tests/test_views.py
@@ -19,7 +19,9 @@ class BookingViewTestCase(TestCase):
def setUp(self):
self.client = Client()
self.slave = JenkinsSlave.objects.create(name='test', url='test')
- self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', url='x')
+ self.owner = User.objects.create(username='owner')
+ self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x',
+ url='x',owner=self.owner)
self.user1 = User.objects.create(username='user1')
self.user1.set_password('user1')
self.user1profile = UserProfile.objects.create(user=self.user1)
diff --git a/pharos-dashboard/booking/views.py b/pharos-dashboard/booking/views.py
index c461aef..c2f437f 100644
--- a/pharos-dashboard/booking/views.py
+++ b/pharos-dashboard/booking/views.py
@@ -5,6 +5,8 @@ from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views import View
from django.views.generic import FormView
+from django.shortcuts import redirect
+from jira import JIRAError
from account.jira_util import get_jira
from booking.forms import BookingForm
@@ -12,20 +14,26 @@ from booking.models import Booking
from dashboard.models import Resource
+def create_jira_ticket(user, booking):
+ jira = get_jira(user)
+ issue_dict = {
+ 'project': 'PHAROS',
+ 'summary': str(booking.resource) + ': Access Request',
+ 'description': booking.purpose,
+ 'issuetype': {'name': 'Task'},
+ 'components': [{'name': 'POD Access Request'}],
+ 'assignee': {'name': booking.resource.owner.username}
+ }
+ issue = jira.create_issue(fields=issue_dict)
+ jira.add_attachment(issue, user.userprofile.pgp_public_key)
+ jira.add_attachment(issue, user.userprofile.ssh_public_key)
+ booking.jira_issue_id = issue.id
+
+
class BookingFormView(LoginRequiredMixin, FormView):
template_name = "booking/booking_calendar.html"
form_class = BookingForm
- def open_jira_issue(self,booking):
- jira = get_jira(self.request.user)
- issue_dict = {
- 'project': 'PHAROS',
- 'summary': 'Booking: ' + str(self.resource),
- 'description': str(booking),
- 'issuetype': {'name': 'Task'},
- }
- jira.create_issue(fields=issue_dict)
-
def dispatch(self, request, *args, **kwargs):
self.resource = get_object_or_404(Resource, id=self.kwargs['resource_id'])
return super(BookingFormView, self).dispatch(request, *args, **kwargs)
@@ -40,9 +48,14 @@ class BookingFormView(LoginRequiredMixin, FormView):
return reverse('booking:create', kwargs=self.kwargs)
def form_valid(self, form):
+ user = self.request.user
+ if not user.userprofile.ssh_public_key or not user.userprofile.pgp_public_key:
+ messages.add_message(self.request, messages.INFO,
+ 'Please upload your private keys before booking')
+ return redirect('account:settings')
booking = Booking(start=form.cleaned_data['start'], end=form.cleaned_data['end'],
purpose=form.cleaned_data['purpose'], resource=self.resource,
- user=self.request.user)
+ user=user)
try:
booking.save()
except ValueError as err:
@@ -51,7 +64,14 @@ class BookingFormView(LoginRequiredMixin, FormView):
except PermissionError as err:
messages.add_message(self.request, messages.ERROR, err)
return super(BookingFormView, self).form_invalid(form)
- self.open_jira_issue(booking)
+ try:
+ create_jira_ticket(user, booking)
+ except JIRAError:
+ messages.add_message(self.request, messages.ERROR, 'Failed to create Jira Ticket. '
+ 'Please check your Jira '
+ 'permissions.')
+ booking.delete()
+ return super(BookingFormView, self).form_invalid(form)
messages.add_message(self.request, messages.SUCCESS, 'Booking saved')
return super(BookingFormView, self).form_valid(form)
diff --git a/pharos-dashboard/dashboard/fixtures/dashboard.json b/pharos-dashboard/dashboard/fixtures/dashboard.json
index d90e99b..f0ac3b2 100644
--- a/pharos-dashboard/dashboard/fixtures/dashboard.json
+++ b/pharos-dashboard/dashboard/fixtures/dashboard.json
@@ -4,7 +4,6 @@
"pk": 1,
"fields": {
"name": "Linux Foundation POD 1",
- "slavename": "lf-pod1",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Lf+Lab"
}
@@ -14,7 +13,6 @@
"pk": 2,
"fields": {
"name": "Linux Foundation POD 2",
- "slavename": "lf-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Lf+Lab"
}
@@ -24,7 +22,6 @@
"pk": 3,
"fields": {
"name": "Ericsson POD 2",
- "slavename": "ericsson-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process"
}
@@ -34,7 +31,6 @@
"pk": 4,
"fields": {
"name": "Intel POD 2",
- "slavename": "intel-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod2"
}
@@ -44,7 +40,6 @@
"pk": 5,
"fields": {
"name": "Intel POD 5",
- "slavename": "intel-pod5",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod5"
}
@@ -54,7 +49,6 @@
"pk": 6,
"fields": {
"name": "Intel POD 6",
- "slavename": "intel-pod6",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod6"
}
@@ -64,7 +58,6 @@
"pk": 7,
"fields": {
"name": "Intel POD 8",
- "slavename": "intel-pod8",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod8"
}
@@ -74,7 +67,6 @@
"pk": 8,
"fields": {
"name": "Huawei POD 1",
- "slavename": "huawei-pod1",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
}
@@ -84,7 +76,6 @@
"pk": 9,
"fields": {
"name": "Intel POD 3",
- "slavename": "intel-pod3",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod3"
}
@@ -94,7 +85,6 @@
"pk": 10,
"fields": {
"name": "Dell POD 1",
- "slavename": "dell-pod1",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting"
}
@@ -104,7 +94,6 @@
"pk": 11,
"fields": {
"name": "Dell POD 2",
- "slavename": "dell-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting"
}
@@ -114,7 +103,6 @@
"pk": 12,
"fields": {
"name": "Orange POD 2",
- "slavename": "orange-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Opnfv-orange-pod2"
}
@@ -124,7 +112,6 @@
"pk": 13,
"fields": {
"name": "Arm POD 1",
- "slavename": "arm-build1",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Enea-pharos-lab"
}
@@ -134,7 +121,6 @@
"pk": 14,
"fields": {
"name": "Ericsson POD 1",
- "slavename": "ericsson-pod1",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process"
}
@@ -144,7 +130,6 @@
"pk": 15,
"fields": {
"name": "Huawei POD 2",
- "slavename": "huawei-pod2",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
}
@@ -154,7 +139,6 @@
"pk": 16,
"fields": {
"name": "Huawei POD 3",
- "slavename": "huawei-pod3",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
}
@@ -164,7 +148,6 @@
"pk": 17,
"fields": {
"name": "Huawei POD 4",
- "slavename": "huawei-pod4",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting"
}
@@ -174,7 +157,6 @@
"pk": 18,
"fields": {
"name": "Intel POD 9",
- "slavename": "intel-pod9",
"description": "Some description",
"url": "https://wiki.opnfv.org/display/pharos/Intel+Pod9"
}
diff --git a/pharos-dashboard/dashboard/models.py b/pharos-dashboard/dashboard/models.py
index 02073e6..971af6a 100644
--- a/pharos-dashboard/dashboard/models.py
+++ b/pharos-dashboard/dashboard/models.py
@@ -10,8 +10,8 @@ class Resource(models.Model):
name = models.CharField(max_length=100, unique=True)
description = models.CharField(max_length=300, blank=True, null=True)
url = models.CharField(max_length=100, blank=True, null=True)
- owners = models.ManyToManyField(User)
- slave = models.ForeignKey(JenkinsSlave, on_delete=models.DO_NOTHING)
+ owner = models.ForeignKey(User)
+ slave = models.ForeignKey(JenkinsSlave, on_delete=models.DO_NOTHING, null=True)
class Meta:
db_table = 'resource'
diff --git a/pharos-dashboard/dashboard/views.py b/pharos-dashboard/dashboard/views.py
index 6af2c1a..56b3a51 100644
--- a/pharos-dashboard/dashboard/views.py
+++ b/pharos-dashboard/dashboard/views.py
@@ -1,4 +1,6 @@
from datetime import timedelta
+
+from django.contrib.auth.models import User
from django.utils import timezone
from django.views.generic import TemplateView
diff --git a/pharos-dashboard/jenkins/models.py b/pharos-dashboard/jenkins/models.py
index f7d54c9..438a882 100644
--- a/pharos-dashboard/jenkins/models.py
+++ b/pharos-dashboard/jenkins/models.py
@@ -21,6 +21,9 @@ class JenkinsSlave(models.Model):
class Meta:
db_table = 'jenkins_slave'
+ def __str__(self):
+ return self.name
+
class JenkinsStatistic(models.Model):
id = models.AutoField(primary_key=True)
diff --git a/pharos-dashboard/pharos_dashboard/settings.py b/pharos-dashboard/pharos_dashboard/settings.py
index a482f95..3678b03 100644
--- a/pharos-dashboard/pharos_dashboard/settings.py
+++ b/pharos-dashboard/pharos_dashboard/settings.py
@@ -123,6 +123,8 @@ USE_L10N = True
USE_TZ = True
+MEDIA_ROOT = '/home/max/tmp/django_media/'
+
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
diff --git a/pharos-dashboard/templates/account/userprofile_update_form.html b/pharos-dashboard/templates/account/userprofile_update_form.html
index 0a921d5..542ea81 100644
--- a/pharos-dashboard/templates/account/userprofile_update_form.html
+++ b/pharos-dashboard/templates/account/userprofile_update_form.html
@@ -13,12 +13,12 @@
</h3>
</div>
<div class="panel-body">
- <form method="post" action="">
+ <form enctype="multipart/form-data" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn btn-success">
- Submit
+ Save
</button>
{% endbuttons %}
</form>
diff --git a/pharos-dashboard/templates/booking/booking_form.html b/pharos-dashboard/templates/booking/booking_form.html
deleted file mode 100644
index f13c4b4..0000000
--- a/pharos-dashboard/templates/booking/booking_form.html
+++ /dev/null
@@ -1,21 +0,0 @@
-{% load bootstrap3 %}
-
-
-{% bootstrap_form_errors form type='non_fields' %}
-<form method="post" action="" class="form" id="bookingform">
- {% csrf_token %}
-
- <div class='input-group' id='starttimepicker'>
- {% bootstrap_field form.start addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
- </div>
- <div class='input-group' id='endtimepicker'>
- {% bootstrap_field form.end addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
- </div>
- {% bootstrap_field form.purpose %}
-
- {% buttons %}
- <button type="submit" class="btn btn btn-success">
- Book
- </button>
- {% endbuttons %}
-</form> \ No newline at end of file
diff --git a/pharos-dashboard/templates/registration/login.html b/pharos-dashboard/templates/registration/login.html
deleted file mode 100644
index 45b9d45..0000000
--- a/pharos-dashboard/templates/registration/login.html
+++ /dev/null
@@ -1,51 +0,0 @@
-{% extends "layout.html" %}
-{% load bootstrap3 %}
-
-{% block basecontent %}
- <div class="container">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- {% if next %}
- <div class="alert alert-dismissable alert-info">
- <button type="button" class="close" data-dismiss="alert" aria-label="Close">
- <span aria-hidden="true">&times;</span>
- </button>
- {% if user.is_authenticated %}
- Your account doesn't have access to this page. To proceed,
- please login with an account that has access.
- {% else %}
- Please login to see this page.
- {% endif %}
- </div>
- {% endif %}
- </div>
- </div>
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- <div class="login-panel panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">
- Login
- </h3>
- </div>
- <div class="panel-body">
- <form method="post">
- {% csrf_token %}
- {% bootstrap_form form %}
- {% buttons %}
- <button type="submit" class="btn btn btn-success">
- Login
- </button>
- <a href="{% url 'account:registration' %}" class="btn btn-info"
- role="button">Register</a>
- {% endbuttons %}
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- {# Assumes you setup the password_reset view in your URLconf #}
- {# <p><a href="{% url 'password_reset' %}">Lost password?</a></p>#}
-{% endblock basecontent %}
diff --git a/pharos-dashboard/templates/registration/registration_form.html b/pharos-dashboard/templates/registration/registration_form.html
deleted file mode 100644
index 0a921d5..0000000
--- a/pharos-dashboard/templates/registration/registration_form.html
+++ /dev/null
@@ -1,30 +0,0 @@
-{% extends "layout.html" %}
-{% load bootstrap3 %}
-
-{% block basecontent %}
- <div class="container">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- {% bootstrap_messages %}
- <div class="login-panel panel panel-default">
- <div class="panel-heading">
- <h3 class="panel-title">
- {{ title }}
- </h3>
- </div>
- <div class="panel-body">
- <form method="post" action="">
- {% csrf_token %}
- {% bootstrap_form form %}
- {% buttons %}
- <button type="submit" class="btn btn btn-success">
- Submit
- </button>
- {% endbuttons %}
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
-{% endblock basecontent %}