aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/account/jira_util.py65
-rw-r--r--src/account/models.py1
-rw-r--r--src/account/tasks.py37
-rw-r--r--src/account/urls.py38
-rw-r--r--src/account/views.py143
-rw-r--r--src/api/views.py2
-rw-r--r--src/booking/quick_deployer.py1
-rw-r--r--src/booking/stats.py2
-rw-r--r--src/booking/urls.py2
-rw-r--r--src/booking/views.py1
-rw-r--r--src/dashboard/templatetags/jira_filters.py17
-rw-r--r--src/dashboard/urls.py2
-rw-r--r--src/laas_dashboard/settings.py76
-rw-r--r--src/notifier/urls.py2
-rw-r--r--src/resource_inventory/urls.py2
-rw-r--r--src/static/package-lock.json91
-rw-r--r--src/templates/base/account/configuration_list.html85
-rw-r--r--src/templates/base/account/details.html1
-rw-r--r--src/templates/base/base.html5
-rw-r--r--src/templates/base/booking/booking_delete.html1
-rw-r--r--src/templates/base/booking/booking_table.html2
-rw-r--r--src/templates/lfedge/booking/booking_table.html2
-rw-r--r--src/workflow/models.py2
23 files changed, 164 insertions, 416 deletions
diff --git a/src/account/jira_util.py b/src/account/jira_util.py
deleted file mode 100644
index a522594..0000000
--- a/src/account/jira_util.py
+++ /dev/null
@@ -1,65 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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 base64
-import os
-
-import oauth2 as oauth
-from django.conf import settings
-from jira import JIRA
-from tlslite.utils import keyfactory
-
-
-class SignatureMethod_RSA_SHA1(oauth.SignatureMethod):
- name = 'RSA-SHA1'
-
- def signing_base(self, request, consumer, token):
- if not hasattr(request, 'normalized_url') or request.normalized_url is None:
- raise ValueError("Base URL for request is not set.")
-
- sig = (
- oauth.escape(request.method),
- oauth.escape(request.normalized_url),
- oauth.escape(request.get_normalized_parameters()),
- )
-
- key = '%s&' % oauth.escape(consumer.secret)
- if token:
- key += oauth.escape(token.secret)
- raw = '&'.join(sig)
- return key, raw
-
- def sign(self, request, consumer, token):
- """Build the base signature string."""
- key, raw = self.signing_base(request, consumer, token)
-
- module_dir = os.path.dirname(__file__) # get current directory
- with open(module_dir + '/rsa.pem', 'r') as f:
- data = f.read()
- privateKeyString = data.strip()
- privatekey = keyfactory.parsePrivateKey(privateKeyString)
- raw = str.encode(raw)
- signature = privatekey.hashAndSign(raw)
- return base64.b64encode(signature)
-
-
-def get_jira(user):
- 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': user.userprofile.oauth_token,
- 'access_token_secret': user.userprofile.oauth_secret,
- 'consumer_key': settings.OAUTH_CONSUMER_KEY,
- 'key_cert': key_cert
- }
-
- return JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
diff --git a/src/account/models.py b/src/account/models.py
index b71f0ac..210025e 100644
--- a/src/account/models.py
+++ b/src/account/models.py
@@ -51,6 +51,7 @@ class UserProfile(models.Model):
oauth_secret = models.CharField(max_length=1024, blank=False)
jira_url = models.CharField(max_length=100, null=True, blank=True, default='')
+
full_name = models.CharField(max_length=100, null=True, blank=True, default='')
booking_privledge = models.BooleanField(default=False)
diff --git a/src/account/tasks.py b/src/account/tasks.py
deleted file mode 100644
index df98c73..0000000
--- a/src/account/tasks.py
+++ /dev/null
@@ -1,37 +0,0 @@
-##############################################################################
-# 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
-##############################################################################
-
-
-from celery import shared_task
-from django.contrib.auth.models import User
-from jira import JIRAError
-
-from account.jira_util import get_jira
-
-
-@shared_task
-def sync_jira_accounts():
- users = User.objects.all()
- for user in users:
- jira = get_jira(user)
- try:
- user_dict = jira.myself()
- except JIRAError:
- # User can be anonymous (local django admin account)
- continue
- try:
- user.email = user_dict['emailAddress']
- except KeyError:
- pass
- user.userprofile.url = user_dict['self']
- user.userprofile.full_name = user_dict['displayName']
-
- user.userprofile.save()
- user.save()
diff --git a/src/account/urls.py b/src/account/urls.py
index 97d8c77..804c133 100644
--- a/src/account/urls.py
+++ b/src/account/urls.py
@@ -30,46 +30,30 @@ from django.urls import path
from account.views import (
AccountSettingsView,
- JiraAuthenticatedView,
- JiraLoginView,
OIDCLoginView,
- JiraLogoutView,
+ LogoutView,
UserListView,
account_resource_view,
account_booking_view,
account_images_view,
- account_configuration_view,
account_detail_view,
- resource_delete_view,
+ template_delete_view,
booking_cancel_view,
image_delete_view,
- configuration_delete_view
)
-from laas_dashboard import settings
+app_name = 'account'
-
-def get_login_view():
- if (settings.AUTH_SETTING == 'LFID'):
- return OIDCLoginView.as_view()
- else:
- return JiraLoginView.as_view()
-
-
-app_name = "account"
urlpatterns = [
url(r'^settings/', AccountSettingsView.as_view(), name='settings'),
- url(r'^authenticated/$', JiraAuthenticatedView.as_view(), name='authenticated'),
- url(r'^login/$', get_login_view(), name='login'),
- url(r'^logout/$', JiraLogoutView.as_view(), name='logout'),
+ url(r'^login/$', OIDCLoginView.as_view(), name='login'),
+ url(r'^logout/$', LogoutView.as_view(), name='logout'),
url(r'^users/$', UserListView.as_view(), name='users'),
- url(r'^my/resources/$', account_resource_view, name="my-resources"),
- path('my/resources/delete/<int:resource_id>', resource_delete_view),
- url(r'^my/bookings/$', account_booking_view, name="my-bookings"),
+ url(r'^my/resources/$', account_resource_view, name='my-resources'),
+ path('my/resources/delete/<int:resource_id>', template_delete_view),
+ url(r'^my/bookings/$', account_booking_view, name='my-bookings'),
path('my/bookings/cancel/<int:booking_id>', booking_cancel_view),
- url(r'^my/images/$', account_images_view, name="my-images"),
+ url(r'^my/images/$', account_images_view, name='my-images'),
path('my/images/delete/<int:image_id>', image_delete_view),
- url(r'^my/configurations/$', account_configuration_view, name="my-configurations"),
- path('my/configurations/delete/<int:config_id>', configuration_delete_view),
- url(r'^my/$', account_detail_view, name="my-account"),
-]
+ url(r'^my/$', account_detail_view, name='my-account'),
+] \ No newline at end of file
diff --git a/src/account/views.py b/src/account/views.py
index b74126e..167b5c4 100644
--- a/src/account/views.py
+++ b/src/account/views.py
@@ -26,13 +26,11 @@ 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 mozilla_django_oidc.auth import OIDCAuthenticationBackend
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 ResourceTemplate, Image
@@ -69,7 +67,7 @@ class MyOIDCAB(OIDCAuthenticationBackend):
If this changes we will need to match users based on some
other criterea.
"""
- username = claims.get(os.environ['CLAIMS_ENDPOINT'] + 'username')
+ username = claims.get(os.environ.get('CLAIMS_ENDPOINT') + 'username')
if not username:
return HttpResponse('No username provided, contact support.')
@@ -101,109 +99,17 @@ class MyOIDCAB(OIDCAuthenticationBackend):
return user
-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 OIDCLoginView(RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('oidc_authentication_init')
-class JiraLogoutView(LoginRequiredMixin, RedirectView):
+class LogoutView(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 = ""
- try:
- email = jira.user(username).emailAddress
- except AttributeError:
- email = ""
- 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"
@@ -232,9 +138,9 @@ def account_resource_view(request):
template = "account/resource_list.html"
active_bundles = [book.resource for book in Booking.objects.filter(
- owner=request.user, end__gte=timezone.now())]
+ owner=request.user, end__gte=timezone.now(), resource__template__temporary=False)]
active_resources = [bundle.template.id for bundle in active_bundles]
- resource_list = list(ResourceTemplate.objects.filter(owner=request.user))
+ resource_list = list(ResourceTemplate.objects.filter(owner=request.user, temporary=False))
context = {
"resources": resource_list,
@@ -262,14 +168,6 @@ def account_booking_view(request):
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(ResourceTemplate.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:
@@ -290,28 +188,19 @@ def account_images_view(request):
return render(request, template, context=context)
-def resource_delete_view(request, resource_id=None):
+def template_delete_view(request, resource_id=None):
if not request.user.is_authenticated:
- return HttpResponse('no') # 403?
- grb = get_object_or_404(ResourceTemplate, 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(ResourceTemplate, pk=config_id)
- if not request.user.id == config.owner.id:
- return HttpResponse('no') # 403?
- if Booking.objects.filter(resource__template=config, end__gt=timezone.now()).exists():
- return HttpResponse('no')
- config.delete()
- return HttpResponse('')
+ return HttpResponse(status=403)
+ template = get_object_or_404(ResourceTemplate, pk=resource_id)
+ if not request.user.id == template.owner.id:
+ return HttpResponse(status=403)
+ if Booking.objects.filter(resource__template=template, end__gt=timezone.now()).exists():
+ return HttpResponse(status=403)
+ #grb.delete()
+ template.public = False
+ template.temporary = True
+ template.save()
+ return HttpResponse(status=200)
def booking_cancel_view(request, booking_id=None):
diff --git a/src/api/views.py b/src/api/views.py
index 1793c79..c0da1bc 100644
--- a/src/api/views.py
+++ b/src/api/views.py
@@ -391,7 +391,7 @@ def available_templates(request):
# mirrors MultipleSelectFilter Widget
avt = []
for lab in Lab.objects.all():
- for template in ResourceTemplate.objects.filter(Q(lab=lab), Q(owner=token.user) | Q(public=True)):
+ for template in ResourceTemplate.objects.filter(Q(owner=token.user) | Q(public=True), lab=lab, temporary=False):
available_resources = lab.get_available_resources()
required_resources = template.get_required_resources()
least_available = 100
diff --git a/src/booking/quick_deployer.py b/src/booking/quick_deployer.py
index 5e5bc8b..9806348 100644
--- a/src/booking/quick_deployer.py
+++ b/src/booking/quick_deployer.py
@@ -227,7 +227,6 @@ def create_from_API(body, user):
data['scenario'] = None
data['image'] = Image.objects.get(pk=booking_info['imageLabID'])
-
data['resource_template'] = ResourceTemplate.objects.get(pk=booking_info['templateID'])
data['lab'] = data['resource_template'].lab
data['owner'] = user
diff --git a/src/booking/stats.py b/src/booking/stats.py
index 626ed79..70f91fa 100644
--- a/src/booking/stats.py
+++ b/src/booking/stats.py
@@ -104,5 +104,5 @@ class StatisticsManager(object):
"user": [x, users],
"utils": [in_use, not_in_use, maintenance],
"projects": [project_keys, project_counts],
- "colors": anuket_colors if os.environ['TEMPLATE_OVERRIDE_DIR'] == 'laas' else lfedge_colors
+ "colors": anuket_colors if os.environ.get('TEMPLATE_OVERRIDE_DIR') == 'laas' else lfedge_colors
}
diff --git a/src/booking/urls.py b/src/booking/urls.py
index cdf18ae..0b60351 100644
--- a/src/booking/urls.py
+++ b/src/booking/urls.py
@@ -38,7 +38,7 @@ from booking.views import (
booking_modify_image
)
-app_name = "booking"
+app_name = 'booking'
urlpatterns = [
url(r'^detail/(?P<booking_id>[0-9]+)/$', booking_detail_view, name='detail'),
url(r'^(?P<booking_id>[0-9]+)/$', booking_detail_view, name='booking_detail'),
diff --git a/src/booking/views.py b/src/booking/views.py
index 2b910e7..a418c82 100644
--- a/src/booking/views.py
+++ b/src/booking/views.py
@@ -127,7 +127,6 @@ class ResourceBookingsJSON(View):
'start',
'end',
'purpose',
- 'jira_issue_status',
'config_bundle__name'
)
return JsonResponse({'bookings': list(bookings)})
diff --git a/src/dashboard/templatetags/jira_filters.py b/src/dashboard/templatetags/jira_filters.py
deleted file mode 100644
index 9a97c1d..0000000
--- a/src/dashboard/templatetags/jira_filters.py
+++ /dev/null
@@ -1,17 +0,0 @@
-##############################################################################
-# Copyright (c) 2016 Max Breitenfeldt 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
-##############################################################################
-
-
-from django.conf import settings
-from django.template.defaultfilters import register
-
-
-@register.filter
-def jira_issue_url(issue):
- return settings.JIRA_URL + '/browse/' + str(issue)
diff --git a/src/dashboard/urls.py b/src/dashboard/urls.py
index d5dad57..c87dacc 100644
--- a/src/dashboard/urls.py
+++ b/src/dashboard/urls.py
@@ -33,7 +33,7 @@ from dashboard.views import (
host_profile_detail_view
)
-app_name = "dashboard"
+app_name = 'dashboard'
urlpatterns = [
url(r'^$', landing_view, name='index'),
url(r'^lab/$', lab_list_view, name='all_labs'),
diff --git a/src/laas_dashboard/settings.py b/src/laas_dashboard/settings.py
index 6b3ed09..010ffde 100644
--- a/src/laas_dashboard/settings.py
+++ b/src/laas_dashboard/settings.py
@@ -15,8 +15,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# SECURITY WARNING: don't run with debug turned on in production!
# NOTE: os.environ only returns strings, so making a comparison to
# 'True' here will convert it to the correct Boolean value.
-DEBUG = os.environ['DEBUG'] == 'True'
-TESTING = os.environ['TEST'] == 'True'
+DEBUG = os.environ.get('DEBUG') == 'True'
+TESTING = os.environ.get('TEST') == 'True'
# Application definition
@@ -53,29 +53,35 @@ MIDDLEWARE = [
'account.middleware.TimezoneMiddleware',
]
-AUTH_SETTING = os.environ.get('AUTH_SETTING', 'JIRA')
-if AUTH_SETTING == 'LFID':
- AUTHENTICATION_BACKENDS = ['account.views.MyOIDCAB']
+#AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend', 'account.views.MyOIDCAB']
+AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']
+
+AUTH_SETTING = os.environ.get('AUTH_SETTING')
+if AUTH_SETTING == 'LFID':
# OpenID Authentications
- OIDC_RP_CLIENT_ID = os.environ['OIDC_CLIENT_ID']
- OIDC_RP_CLIENT_SECRET = os.environ['OIDC_CLIENT_SECRET']
+ AUTHENTICATION_BACKENDS.append('account.views.MyOIDCAB')
+ OIDC_RP_CLIENT_ID = os.environ.get('OIDC_CLIENT_ID')
+ OIDC_RP_CLIENT_SECRET = os.environ.get('OIDC_CLIENT_SECRET')
- OIDC_OP_AUTHORIZATION_ENDPOINT = os.environ['OIDC_AUTHORIZATION_ENDPOINT']
- OIDC_OP_TOKEN_ENDPOINT = os.environ['OIDC_TOKEN_ENDPOINT']
- OIDC_OP_USER_ENDPOINT = os.environ['OIDC_USER_ENDPOINT']
+ OIDC_OP_AUTHORIZATION_ENDPOINT = os.environ.get('OIDC_AUTHORIZATION_ENDPOINT')
+ OIDC_OP_TOKEN_ENDPOINT = os.environ.get('OIDC_TOKEN_ENDPOINT')
+ OIDC_OP_USER_ENDPOINT = os.environ.get('OIDC_USER_ENDPOINT')
- LOGIN_REDIRECT_URL = os.environ['DASHBOARD_URL']
- LOGOUT_REDIRECT_URL = os.environ['DASHBOARD_URL']
+ LOGIN_REDIRECT_URL = os.environ.get('DASHBOARD_URL')
+ LOGOUT_REDIRECT_URL = os.environ.get('DASHBOARD_URL')
- OIDC_RP_SIGN_ALGO = os.environ["OIDC_RP_SIGN_ALGO"]
+ OIDC_RP_SIGN_ALGO = os.environ.get("OIDC_RP_SIGN_ALGO")
+ #raise Exception("OIDC rp sign algo is: ", OIDC_RP_SIGN_ALGO)
if OIDC_RP_SIGN_ALGO == "RS256":
- OIDC_OP_JWKS_ENDPOINT = os.environ["OIDC_OP_JWKS_ENDPOINT"]
+ OIDC_OP_JWKS_ENDPOINT = os.environ.get("OIDC_OP_JWKS_ENDPOINT")
+else:
+ raise Exception('AUTH_SETTING set to invalid value')
# This is for LFID auth setups w/ an HTTPS proxy
-if os.environ['EXPECT_HOST_FORWARDING'] == 'True':
+if os.environ.get('EXPECT_HOST_FORWARDING') == 'True':
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', "https")
USE_X_FORWARDED_HOST = True
@@ -162,7 +168,7 @@ STATICFILES_DIRS = [
LOGIN_REDIRECT_URL = '/'
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = os.environ['SECRET_KEY']
+SECRET_KEY = os.environ.get('SECRET_KEY')
BOOTSTRAP3 = {
'set_placeholder': False,
@@ -175,11 +181,11 @@ ALLOWED_HOSTS = ['*']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
- 'NAME': os.environ['DB_NAME'],
- 'USER': os.environ['DB_USER'],
- 'PASSWORD': os.environ['DB_PASS'],
- 'HOST': os.environ['DB_SERVICE'],
- 'PORT': os.environ['DB_PORT']
+ 'NAME': os.environ.get('DB_NAME'),
+ 'USER': os.environ.get('DB_USER'),
+ 'PASSWORD': os.environ.get('DB_PASS'),
+ 'HOST': os.environ.get('DB_SERVICE'),
+ 'PORT': os.environ.get('DB_PORT')
}
}
@@ -198,27 +204,17 @@ REST_FRAMEWORK = {
MEDIA_ROOT = '/media'
STATIC_ROOT = '/static'
-# Jira Settings
-CREATE_JIRA_TICKET = False
-
-JIRA_URL = os.environ['JIRA_URL']
-
-JIRA_USER_NAME = os.environ['JIRA_USER_NAME']
-JIRA_USER_PASSWORD = os.environ['JIRA_USER_PASSWORD']
-
-OAUTH_CONSUMER_KEY = os.environ['OAUTH_CONSUMER_KEY']
-OAUTH_CONSUMER_SECRET = os.environ['OAUTH_CONSUMER_SECRET']
-
-OAUTH_REQUEST_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/request-token'
-OAUTH_ACCESS_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/access-token'
-OAUTH_AUTHORIZE_URL = JIRA_URL + '/plugins/servlet/oauth/authorize'
+OAUTH_CONSUMER_KEY = os.environ.get('OAUTH_CONSUMER_KEY')
+OAUTH_CONSUMER_SECRET = os.environ.get('OAUTH_CONSUMER_SECRET')
-OAUTH_CALLBACK_URL = os.environ['DASHBOARD_URL'] + '/accounts/authenticated'
+OAUTH_CALLBACK_URL = os.environ.get('DASHBOARD_URL') + '/accounts/authenticated'
# Celery Settings
CELERY_TIMEZONE = 'UTC'
RABBITMQ_URL = 'rabbitmq'
+#RABBITMQ_DEFAULT_USER = os.environ['DEFAULT_USER']
+#RABBITMQ_DEFAULT_PASS = os.environ['DEFAULT_PASS']
RABBITMQ_DEFAULT_USER = os.environ['RABBITMQ_DEFAULT_USER']
RABBITMQ_DEFAULT_PASS = os.environ['RABBITMQ_DEFAULT_PASS']
@@ -248,10 +244,10 @@ CELERYBEAT_SCHEDULE = {
}
# Notifier Settings
-EMAIL_HOST = os.environ['EMAIL_HOST']
-EMAIL_PORT = os.environ['EMAIL_PORT']
-EMAIL_HOST_USER = os.environ['EMAIL_HOST_USER']
-EMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']
+EMAIL_HOST = os.environ.get('EMAIL_HOST')
+EMAIL_PORT = os.environ.get('EMAIL_PORT')
+EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
+EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = True
DEFAULT_EMAIL_FROM = os.environ.get('DEFAULT_EMAIL_FROM', 'webmaster@localhost')
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
diff --git a/src/notifier/urls.py b/src/notifier/urls.py
index fedb9e8..923cc33 100644
--- a/src/notifier/urls.py
+++ b/src/notifier/urls.py
@@ -12,7 +12,7 @@ from django.conf.urls import url
from notifier.views import InboxView, NotificationView
-app_name = "notifier"
+app_name = 'notifier'
urlpatterns = [
url(r'^$', InboxView, name='messages'),
url(r'^notification/(?P<notification_id>[0-9]+)/$', NotificationView, name='notifier_single')
diff --git a/src/resource_inventory/urls.py b/src/resource_inventory/urls.py
index a008176..a9a4d43 100644
--- a/src/resource_inventory/urls.py
+++ b/src/resource_inventory/urls.py
@@ -29,7 +29,7 @@ from django.conf.urls import url
from resource_inventory.views import HostView, hostprofile_detail_view
-app_name = "resource"
+app_name = 'resource'
urlpatterns = [
url(r'^hosts$', HostView.as_view(), name='hosts'),
url(r'^profiles/(?P<hostprofile_id>.+)/$', hostprofile_detail_view, name='host_detail'),
diff --git a/src/static/package-lock.json b/src/static/package-lock.json
index f8eabe4..89a26db 100644
--- a/src/static/package-lock.json
+++ b/src/static/package-lock.json
@@ -1,8 +1,97 @@
{
"name": "laas",
"version": "1.0.0",
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "laas",
+ "version": "1.0.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@fortawesome/fontawesome-free": "^5.12.0",
+ "bootstrap": "^4.4.1",
+ "datatables.net-bs4": "^1.10.20",
+ "datatables.net-responsive-bs4": "^2.2.3",
+ "jquery": "^3.4.1",
+ "mxgraph": "^4.0.6",
+ "plotly.js-dist": "^1.51.3",
+ "popper.js": "^1.16.0"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-free": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.12.0.tgz",
+ "integrity": "sha512-vKDJUuE2GAdBERaQWmmtsciAMzjwNrROXA5KTGSZvayAsmuTGjam5z6QNqNPCwDfVljLWuov1nEC3mEQf/n6fQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/bootstrap": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
+ "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/datatables.net": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz",
+ "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==",
+ "dependencies": {
+ "jquery": "3.4.1"
+ }
+ },
+ "node_modules/datatables.net-bs4": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net-bs4/-/datatables.net-bs4-1.10.20.tgz",
+ "integrity": "sha512-kQmMUMsHMOlAW96ztdoFqjSbLnlGZQ63iIM82kHbmldsfYdzuyhbb4hTx6YNBi481WCO3iPSvI6YodNec46ZAw==",
+ "dependencies": {
+ "datatables.net": "1.10.20",
+ "jquery": "3.4.1"
+ }
+ },
+ "node_modules/datatables.net-responsive": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/datatables.net-responsive/-/datatables.net-responsive-2.2.3.tgz",
+ "integrity": "sha512-8D6VtZcyuH3FG0Hn5A4LPZQEOX3+HrRFM7HjpmsQc/nQDBbdeBLkJX4Sh/o1nzFTSneuT1Wh/lYZHVPpjcN+Sw==",
+ "dependencies": {
+ "datatables.net": "1.10.20",
+ "jquery": "3.4.1"
+ }
+ },
+ "node_modules/datatables.net-responsive-bs4": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/datatables.net-responsive-bs4/-/datatables.net-responsive-bs4-2.2.3.tgz",
+ "integrity": "sha512-SQaWI0uLuPcaiBBin9zX+MuQfTSIkK1bYxbXqUV6NLkHCVa6PMQK7Rvftj0ywG4R7uOtjbzY8nSVqxEKvQI0Vg==",
+ "dependencies": {
+ "datatables.net-bs4": "1.10.20",
+ "datatables.net-responsive": "2.2.3",
+ "jquery": "3.4.1"
+ }
+ },
+ "node_modules/jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ },
+ "node_modules/mxgraph": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/mxgraph/-/mxgraph-4.0.6.tgz",
+ "integrity": "sha512-5XZXeAkA4k6n4BS05Fxd2cNhMw+3dnlRqAaLtsuXdT0g8BvvEa1VT4jjuGtUW4QTt38Q+I2Dr/3EWiAaGRfAXw=="
+ },
+ "node_modules/plotly.js-dist": {
+ "version": "1.51.3",
+ "resolved": "https://registry.npmjs.org/plotly.js-dist/-/plotly.js-dist-1.51.3.tgz",
+ "integrity": "sha512-Bxz0XBg963gpnbt7FVPEhYvT33JsaKa0hEozXBnQZkiKtsiM2M1lZN6tkEHmq6o1N2K6qJXFtdzCXbZ/hLGV0Q=="
+ },
+ "node_modules/popper.js": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.0.tgz",
+ "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw=="
+ }
+ },
"dependencies": {
"@fortawesome/fontawesome-free": {
"version": "5.12.0",
diff --git a/src/templates/base/account/configuration_list.html b/src/templates/base/account/configuration_list.html
deleted file mode 100644
index fee6e83..0000000
--- a/src/templates/base/account/configuration_list.html
+++ /dev/null
@@ -1,85 +0,0 @@
-{% extends "base.html" %}
-{% block content %}
-<div class="row">
-{% for config in configurations %}
- <div class="col-12 col-md-6 col-lg-4 col-xl-3 mb-3">
- <div class="card h-100">
- <div class="card-header">
- <h3>Configuration {{config.id}}</h3>
- </div>
- <ul class="list-group list-group-flush h-100">
- <li class="list-group-item">id: {{config.id}}</li>
- <li class="list-group-item">name: {{config.name}}</li>
- <li class="list-group-item">description: {{config.description}}</li>
- <li class="list-group-item">resource: {{config.bundle}}</li>
- </ul>
- <div class="card-footer">
- <button
- class="btn btn-danger w-100"
- onclick='delete_config({{config.id}});'
- data-toggle="modal"
- data-target="#configModal"
- >Delete</button>
- </div>
- </div>
- </div>
-{% empty %}
- <div class="col">
- <p>You don't have any configurations. You can create a configuration by configuring a pod.</p>
- </div>
-{% endfor %}
-</div>
-
-<script>
- var current_config_id = -1;
- function delete_config(config_id) {
- current_config_id = config_id;
- }
-
- function submit_delete_form() {
- var ajaxForm = $("#config_delete_form");
- var formData = ajaxForm.serialize();
- req = new XMLHttpRequest();
- var url = "delete/" + current_config_id;
- req.onreadystatechange = function() {
- if (this.readyState == 4 && this.status == 200) {
- location.reload();
- }
- };
- req.open("POST", url, true);
- req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- req.onerror = function() { alert("problem submitting form"); }
- req.send(formData);
- }
-</script>
-
-<div class="modal fade" id="configModal" tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title d-inline float-left">Delete Configuration?</h4>
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">&times;</span>
- </button>
- </div>
- <form id="config_delete_form">
- {% csrf_token %}
- </form>
- <div class="modal-footer d-flex flex-column">
- <div class="mb-2">
- <button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
- <button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#warning">Delete</button>
- </div>
- <div class="collapse w-100 text-center border-top" id="warning">
- <div class="p-4">
- <h3>Are You Sure?</h3>
- <p>This cannot be undone</p>
- <button class="btn btn-outline-secondary" data-dismiss="modal">Nevermind</button>
- <button class="btn btn-danger" data-dismiss="modal" onclick="submit_delete_form();">I'm Sure</button>
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
-{% endblock %}
diff --git a/src/templates/base/account/details.html b/src/templates/base/account/details.html
index 3092ad0..ad59c9a 100644
--- a/src/templates/base/account/details.html
+++ b/src/templates/base/account/details.html
@@ -4,6 +4,5 @@
<h1>Account Details</h1>
<a class="btn btn-primary" href="{% url 'account:my-resources' %}">My Resources</a>
<a class="btn btn-primary" href="{% url 'account:my-bookings' %}">My Bookings</a>
-<a class="btn btn-primary" href="{% url 'account:my-configurations' %}">My Configurations</a>
<a class="btn btn-primary" href="{% url 'account:my-images' %}">My Snapshots</a>
{% endblock content %}
diff --git a/src/templates/base/base.html b/src/templates/base/base.html
index 394ddec..f334a63 100644
--- a/src/templates/base/base.html
+++ b/src/templates/base/base.html
@@ -87,7 +87,7 @@
{% else %}
<a href="{% url 'account:login' %}" class="text-dark dropdown-item">
<i class="fas fa-sign-in-alt"></i>
- Login with Jira
+ Login
</a>
{% endif %}
{% endif %}
@@ -156,9 +156,6 @@
<a href="{% url 'account:my-bookings' %}" class="list-group-item list-group-item-action list-group-item-secondary">
My Bookings
</a>
- <a href="{% url 'account:my-configurations' %}" class="list-group-item list-group-item-action list-group-item-secondary">
- My Configurations
- </a>
<a href="{% url 'account:my-images' %}" class="list-group-item list-group-item-action list-group-item-secondary">
My Snapshots
</a>
diff --git a/src/templates/base/booking/booking_delete.html b/src/templates/base/booking/booking_delete.html
index b89eb15..4afa370 100644
--- a/src/templates/base/booking/booking_delete.html
+++ b/src/templates/base/booking/booking_delete.html
@@ -1,4 +1,3 @@
-{% load jira_filters %}
{% load bootstrap4 %}
<p>
diff --git a/src/templates/base/booking/booking_table.html b/src/templates/base/booking/booking_table.html
index 32a0146..9c8341c 100644
--- a/src/templates/base/booking/booking_table.html
+++ b/src/templates/base/booking/booking_table.html
@@ -1,4 +1,4 @@
-{% load jira_filters %}
+
<thead>
diff --git a/src/templates/lfedge/booking/booking_table.html b/src/templates/lfedge/booking/booking_table.html
index 4afb4d2..4020b5e 100644
--- a/src/templates/lfedge/booking/booking_table.html
+++ b/src/templates/lfedge/booking/booking_table.html
@@ -1,4 +1,4 @@
-{% load jira_filters %}
+
<thead>
diff --git a/src/workflow/models.py b/src/workflow/models.py
index f550a38..91a216c 100644
--- a/src/workflow/models.py
+++ b/src/workflow/models.py
@@ -160,7 +160,7 @@ class BookingAuthManager():
return True # admin override for this user
if Booking.objects.filter(owner=booking.owner, end__gt=timezone.now()).count() >= 3:
return False
- if len(booking.resource.template.getResources()) < 2:
+ if len(booking.resource.template.get_required_resources()) < 2:
return True # if they only have one server, we dont care
if repo.BOOKING_INFO_FILE not in repo.el:
return False # INFO file not provided