aboutsummaryrefslogtreecommitdiffstats
path: root/opnfv_testapi/resources
diff options
context:
space:
mode:
Diffstat (limited to 'opnfv_testapi/resources')
-rw-r--r--opnfv_testapi/resources/application_handlers.py84
-rw-r--r--opnfv_testapi/resources/handlers.py15
-rw-r--r--opnfv_testapi/resources/result_handlers.py40
-rw-r--r--opnfv_testapi/resources/review_handlers.py119
-rw-r--r--opnfv_testapi/resources/review_models.py39
-rw-r--r--opnfv_testapi/resources/test_handlers.py47
6 files changed, 299 insertions, 45 deletions
diff --git a/opnfv_testapi/resources/application_handlers.py b/opnfv_testapi/resources/application_handlers.py
index 7cecd3e..7d823b8 100644
--- a/opnfv_testapi/resources/application_handlers.py
+++ b/opnfv_testapi/resources/application_handlers.py
@@ -6,15 +6,20 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
+from datetime import datetime
import logging
import json
+import os
from tornado import web
from tornado import gen
from bson import objectid
+from slugify import slugify
+from PIL import Image
from opnfv_testapi.common.config import CONF
from opnfv_testapi.common import utils
+from opnfv_testapi.db import api as dbapi
from opnfv_testapi.resources import handlers
from opnfv_testapi.resources import application_models
from opnfv_testapi.tornado_swagger import swagger
@@ -34,19 +39,28 @@ class ApplicationsLogoHandler(GenericApplicationHandler):
@web.asynchronous
@gen.coroutine
def post(self):
- role = self.get_secure_cookie(auth_const.ROLE)
- if role.find('administrator') == -1:
- msg = 'Only administrator is allowed to upload logos'
- self.finish_request({'code': '-1', 'msg': msg})
- return
-
fileinfo = self.request.files['file'][0]
- fname = fileinfo['filename']
+ company_logo_name = self.request.arguments['company_name'][0]
+ extension_name = fileinfo['filename'].split('.')[-1]
+ company_logo_name = slugify(company_logo_name)
+ fileinfo['filename'] = company_logo_name
location = 'media/companies/'
- fh = open(location + fname, 'w')
+ full_name_path = location + company_logo_name + '.' + extension_name
+ fh = open(full_name_path, 'w')
fh.write(fileinfo['body'])
- msg = 'Successfully uploaded logo: ' + fname
- resp = {'code': '1', 'msg': msg}
+ fh.close()
+ img = Image.open(full_name_path)
+ if (img.size[0] > 165) or (img.size[1] > 40):
+ os.remove(full_name_path)
+ msg = 'The size of the image is not according to the compliance' \
+ ' program. Please try again, loading an image with proper' \
+ ' dimensions (Max Values: 165px width and 40px height).'
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+
+ msg = 'Successfully uploaded logo: ' + company_logo_name
+ resp = {'code': 0, 'msg': msg,
+ 'filename': company_logo_name + '.' + extension_name}
self.finish_request(resp)
@@ -130,6 +144,8 @@ class ApplicationsCLHandler(GenericApplicationHandler):
openid = self.get_secure_cookie(auth_const.OPENID)
if openid:
self.json_args['owner'] = openid
+ if self.is_onap:
+ self.json_args['is_onap'] = 'true'
self._post()
@@ -138,22 +154,21 @@ class ApplicationsCLHandler(GenericApplicationHandler):
miss_fields = []
carriers = []
- role = self.get_secure_cookie(auth_const.ROLE)
- if role.find('administrator') == -1:
- self.finish_request({'code': '403', 'msg': 'Only administrator \
- is allowed to submit application.'})
- return
-
- query = {"openid": self.json_args['user_id']}
- table = "users"
- ret, msg = yield self._check_if_exists(table=table, query=query)
+ query = {'openid': self.json_args['owner']}
+ ret, msg = yield self._check_if_exists(table='users', query=query)
logging.debug('ret:%s', ret)
if not ret:
- self.finish_request({'code': '403', 'msg': msg})
+ self.finish_request({'code': 403, 'msg': msg})
+ return
+ query = {'test_id': self.json_args['test_id']}
+ ret, _ = yield self._check_if_exists(table=self.table, query=query)
+ if ret:
+ msg = 'An application for these test results already exists'
+ self.finish_request({'code': 403, 'msg': msg})
return
self._create(miss_fields=miss_fields, carriers=carriers)
- self._send_email()
+ # self._send_email()
def _send_email(self):
@@ -173,7 +188,6 @@ This is a new application:
Primary Email: {},
Primary Address: {},
Primary Phone: {},
- User ID Type: {},
User ID: {}
Best Regards,
@@ -188,19 +202,26 @@ CVP Team
data.prim_email,
data.prim_address,
data.prim_phone,
- data.id_type,
- data.user_id)
+ data.owner)
utils.send_email(subject, content)
class ApplicationsGURHandler(GenericApplicationHandler):
@swagger.operation(nickname="deleteAppById")
+ @gen.coroutine
def delete(self, id):
query = {'_id': objectid.ObjectId(id)}
+ application = yield dbapi.db_find_one(self.table, query)
+ test_id = application['test_id']
+ t_query = {'id': test_id}
+ yield dbapi.db_delete('reviews', {'test_id': test_id})
+ yield dbapi.db_update('tests', t_query,
+ {'$set': {'status': 'private'}})
self._delete(query=query)
@swagger.operation(nickname="updateApplicationById")
+ @web.asynchronous
def put(self, application_id):
"""
@description: update a single application by id
@@ -222,12 +243,23 @@ class ApplicationsGURHandler(GenericApplicationHandler):
logging.error('except:%s', e)
return
- @web.asynchronous
@gen.coroutine
def update(self, application_id, item, value):
self.json_args = {}
self.json_args[item] = value
- query = {'_id': application_id, 'owner':
+ query = {'_id': objectid.ObjectId(application_id), 'owner':
self.get_secure_cookie(auth_const.OPENID)}
db_keys = ['_id', 'owner']
+ if item == 'approved':
+ if value == 'true':
+ status = 'verified'
+ self.json_args['approve_date'] = str(datetime.now())
+ else:
+ status = 'review'
+ self.json_args['approve_date'] = ''
+ application = yield dbapi.db_find_one(self.table, query)
+ test_id = application['test_id']
+ t_query = {'id': test_id}
+ yield dbapi.db_update('tests', t_query,
+ {'$set': {'status': status}})
self._update(query=query, db_keys=db_keys)
diff --git a/opnfv_testapi/resources/handlers.py b/opnfv_testapi/resources/handlers.py
index e8c81f3..559e689 100644
--- a/opnfv_testapi/resources/handlers.py
+++ b/opnfv_testapi/resources/handlers.py
@@ -41,6 +41,7 @@ DEFAULT_REPRESENTATION = "application/json"
class GenericApiHandler(web.RequestHandler):
def __init__(self, application, request, **kwargs):
+ self.is_onap = False
super(GenericApiHandler, self).__init__(application, request, **kwargs)
self.json_args = None
self.table = None
@@ -52,6 +53,9 @@ class GenericApiHandler(web.RequestHandler):
self.db_scenarios = 'scenarios'
self.auth = self.settings["auth"]
+ def initialize(self, is_onap=False):
+ self.is_onap = is_onap
+
def get_int(self, key, value):
try:
value = int(value)
@@ -97,6 +101,11 @@ class GenericApiHandler(web.RequestHandler):
if role.find("reviewer") != -1:
query['$or'].append({"status": {"$ne": "private"}})
+ elif k == 'status':
+ if v.startswith('{'):
+ query[k] = json.loads(v)
+ else:
+ query[k] = v
elif k not in ['last', 'page', 'descend', 'per_page']:
query[k] = v
if date_range:
@@ -107,6 +116,8 @@ class GenericApiHandler(web.RequestHandler):
if 'start_date' in query and '$lt' not in query['start_date']:
query['start_date'].update({'$lt': str(datetime.now())})
+ query['is_onap'] = 'true' if self.is_onap else None
+
logging.debug("query:%s", query)
raise gen.Return((query))
@@ -184,7 +195,7 @@ class GenericApiHandler(web.RequestHandler):
if query and table:
data = yield dbapi.db_find_one(table, query)
if data:
- raise gen.Return((True, 'Data alreay exists. %s' % (query)))
+ raise gen.Return((True, 'Data already exists. %s' % (query)))
raise gen.Return((False, 'Data does not exist. %s' % (query)))
# @web.asynchronous
@@ -214,7 +225,7 @@ class GenericApiHandler(web.RequestHandler):
if res_op is None:
res = {self.table: data}
else:
- res = res_op(data, *args)
+ res = yield res_op(data, *args)
if page > 0:
res.update({
'pagination': {
diff --git a/opnfv_testapi/resources/result_handlers.py b/opnfv_testapi/resources/result_handlers.py
index 38109ad..9501bfd 100644
--- a/opnfv_testapi/resources/result_handlers.py
+++ b/opnfv_testapi/resources/result_handlers.py
@@ -20,6 +20,7 @@ from bson import objectid
from opnfv_testapi.common.config import CONF
from opnfv_testapi.common import message
from opnfv_testapi.common import raises
+from opnfv_testapi.db import api as dbapi
from opnfv_testapi.resources import handlers
from opnfv_testapi.resources import result_models
from opnfv_testapi.tornado_swagger import swagger
@@ -41,6 +42,7 @@ class GenericResultHandler(handlers.GenericApiHandler):
raises.BadRequest(message.must_int(key))
return value
+ @gen.coroutine
def set_query(self):
query = dict()
date_range = dict()
@@ -82,11 +84,15 @@ class GenericResultHandler(handlers.GenericApiHandler):
if 'start_date' in query and '$lt' not in query['start_date']:
query['start_date'].update({'$lt': str(datetime.now())})
- return query
+ query['is_onap'] = 'true' if self.is_onap else None
+
+ raise gen.Return((query))
class ResultsCLHandler(GenericResultHandler):
@swagger.operation(nickname="queryTestResults")
+ @web.asynchronous
+ @gen.coroutine
def get(self):
"""
@description: Retrieve result(s) for a test project
@@ -195,7 +201,8 @@ class ResultsCLHandler(GenericResultHandler):
'per_page': CONF.api_results_per_page
}
- self._list(query=self.set_query(), **limitations)
+ query = yield self.set_query()
+ yield self._list(query=query, **limitations)
@swagger.operation(nickname="createTestResult")
def post(self):
@@ -267,10 +274,19 @@ class ResultsUploadHandler(ResultsCLHandler):
results = results.split('\n')
result_ids = []
version = ''
+ vnf_type = None
+ vnf_checksum = None
for result in results:
if result == '':
continue
self.json_args = json.loads(result).copy()
+ openid = self.get_secure_cookie(auth_const.OPENID)
+ if openid:
+ self.json_args['owner'] = openid
+ if self.is_onap:
+ self.json_args['is_onap'] = 'true'
+ vnf_type = self.json_args['vnf_type']
+ vnf_checksum = self.json_args['vnf_checksum']
# the result files used in the first release of OVP did not
# specify an OVP version
if (self.json_args['version'] == 'master'
@@ -288,14 +304,30 @@ class ResultsUploadHandler(ResultsCLHandler):
with open(log_filename, "wb") as tar_out:
tar_out.write(fileinfo['body'])
resp = {'id': test_id, 'results': result_ids, 'version': version}
+ if vnf_type:
+ resp['vnf_type'] = vnf_type
+ resp['vnf_checksum'] = vnf_checksum
self.finish_request(resp)
class ResultsGURHandler(GenericResultHandler):
@swagger.operation(nickname='DeleteTestResultById')
+ @gen.coroutine
def delete(self, result_id):
- query = {'_id': objectid.ObjectId(result_id)}
- self._delete(query=query)
+ curr_user = self.get_secure_cookie(auth_const.OPENID)
+ curr_user_role = self.get_secure_cookie(auth_const.ROLE)
+ if curr_user is not None:
+ query = {'_id': objectid.ObjectId(result_id)}
+ test_data = yield dbapi.db_find_one(self.table, query)
+ if not test_data:
+ raises.NotFound(message.not_found(self.table, query))
+ if curr_user == test_data['owner'] or \
+ curr_user_role.find('administrator') != -1:
+ self._delete(query=query)
+ else:
+ raises.Forbidden(message.no_auth())
+ else:
+ raises.Unauthorized(message.no_auth())
@swagger.operation(nickname='getTestResultById')
def get(self, result_id):
diff --git a/opnfv_testapi/resources/review_handlers.py b/opnfv_testapi/resources/review_handlers.py
new file mode 100644
index 0000000..9731e0f
--- /dev/null
+++ b/opnfv_testapi/resources/review_handlers.py
@@ -0,0 +1,119 @@
+##############################################################################
+# Copyright (c) 2019 Intracom Telecom
+# mokats@intracom-telecom.com
+# 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 datetime import datetime
+import logging
+
+from tornado import web, gen
+
+from opnfv_testapi.common.config import CONF
+from opnfv_testapi.common import message, raises
+from opnfv_testapi.db import api as dbapi
+from opnfv_testapi.resources import handlers, review_models
+from opnfv_testapi.tornado_swagger import swagger
+from opnfv_testapi.ui.auth import constants as auth_const
+
+
+class GenericReviewHandler(handlers.GenericApiHandler):
+ def __init__(self, review, request, **kwargs):
+ super(GenericReviewHandler, self).__init__(review, request, **kwargs)
+ self.table = 'reviews'
+ self.table_cls = review_models.Review
+
+
+class ReviewsCLHandler(GenericReviewHandler):
+ @swagger.operation(nickname="queryReviews")
+ @web.asynchronous
+ @gen.coroutine
+ def get(self):
+ def descend_limit():
+ descend = self.get_query_argument('descend', 'true')
+ return -1 if descend.lower() == 'true' else 1
+
+ def last_limit():
+ return self.get_int('last', self.get_query_argument('last', 0))
+
+ def page_limit():
+ return self.get_int('page', self.get_query_argument('page', 0))
+
+ limitations = {
+ 'sort': {'_id': descend_limit()},
+ 'last': last_limit(),
+ 'page': page_limit(),
+ 'per_page': CONF.api_results_per_page
+ }
+
+ query = yield self.set_query()
+ yield self._list(query=query, **limitations)
+ logging.debug('list end')
+
+ @swagger.operation(nickname="createReview")
+ @web.asynchronous
+ def post(self):
+ openid = self.get_secure_cookie(auth_const.OPENID)
+ if openid:
+ self.json_args['reviewer_openid'] = openid
+
+ if self.json_args['outcome'] is None:
+ self._del()
+ else:
+ self._post()
+
+ @gen.coroutine
+ def _post(self):
+ query = {'openid': self.json_args['reviewer_openid']}
+ user = yield dbapi.db_find_one('users', query)
+ if not user:
+ raises.Forbidden(message.unauthorized())
+ role = self.get_secure_cookie(auth_const.ROLE)
+ if 'reviewer' not in role.split(','):
+ raises.Unauthorized(message.no_auth())
+ test = yield dbapi.db_find_one(
+ 'tests', {'id': self.json_args['test_id']})
+ if test['owner'] == self.json_args['reviewer_openid']:
+ self.finish_request({'code': 403,
+ 'msg': 'No permision to review own results'})
+ return
+ query = {
+ 'reviewer_openid': self.json_args['reviewer_openid'],
+ 'test_id': self.json_args['test_id']
+ }
+ review = yield dbapi.db_find_one(self.table, query)
+ if review:
+ if review['outcome'] != self.json_args['outcome']:
+ yield dbapi.db_update(self.table, query,
+ {'$set': {
+ 'outcome': self.json_args['outcome'],
+ 'creation_date': datetime.now()}})
+ self.finish_request()
+ else:
+ self.json_args['reviewer_name'] = user['fullname']
+ self.json_args['reviewer_email'] = user['email']
+ self._create(miss_fields=[], carriers=[])
+
+ @gen.coroutine
+ def _del(self):
+ query = {'openid': self.json_args['reviewer_openid']}
+ user = yield dbapi.db_find_one('users', query)
+ if not user:
+ raises.Forbidden(message.unauthorized())
+ role = self.get_secure_cookie(auth_const.ROLE)
+ if 'reviewer' not in role.split(','):
+ raises.Unauthorized(message.no_auth())
+ test = yield dbapi.db_find_one(
+ 'tests', {'id': self.json_args['test_id']})
+ if test['owner'] == self.json_args['reviewer_openid']:
+ self.finish_request({'code': 403,
+ 'msg': 'No permision to review own results'})
+ return
+ query = {
+ 'reviewer_openid': self.json_args['reviewer_openid'],
+ 'test_id': self.json_args['test_id']
+ }
+ yield dbapi.db_delete(self.table, query)
+ self.finish_request()
diff --git a/opnfv_testapi/resources/review_models.py b/opnfv_testapi/resources/review_models.py
new file mode 100644
index 0000000..2aaa62c
--- /dev/null
+++ b/opnfv_testapi/resources/review_models.py
@@ -0,0 +1,39 @@
+##############################################################################
+# Copyright (c) 2019
+# 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 opnfv_testapi.resources import models
+from opnfv_testapi.tornado_swagger import swagger
+
+from datetime import datetime
+
+
+@swagger.model()
+class Review(models.ModelBase):
+ def __init__(self, _id=None, test_id=None, reviewer_openid=None,
+ reviewer_email=None, reviewer_name=None, creation_date=None,
+ outcome=None):
+ self._id = _id
+ self.test_id = test_id
+ self.reviewer_openid = reviewer_openid
+ self.reviewer_email = reviewer_email
+ self.reviewer_name = reviewer_name
+ self.creation_date = datetime.now()
+ self.outcome = outcome
+
+
+@swagger.model()
+class Reviews(models.ModelBase):
+ """
+ @property reviews:
+ @ptype tests: C{list} of L{Review}
+ """
+ def __init__(self):
+ self.reviews = list()
+
+ @staticmethod
+ def attr_parser():
+ return {'reviews': Review}
diff --git a/opnfv_testapi/resources/test_handlers.py b/opnfv_testapi/resources/test_handlers.py
index 5ecb176..7ab20dc 100644
--- a/opnfv_testapi/resources/test_handlers.py
+++ b/opnfv_testapi/resources/test_handlers.py
@@ -78,10 +78,28 @@ class TestsCLHandler(GenericTestHandler):
if curr_user is None:
raises.Unauthorized(message.no_auth())
+ review = self.request.query_arguments.pop('review', None)
query = yield self.set_query()
- yield self._list(query=query, **limitations)
+ if review:
+ yield self._list(query=query, res_op=self.check_review,
+ **limitations)
+ else:
+ yield self._list(query=query, **limitations)
logging.debug('list end')
+ @gen.coroutine
+ def check_review(self, data, *args):
+ current_user = self.get_secure_cookie(auth_const.OPENID)
+ for test in data:
+ query = {'reviewer_openid': current_user, 'test_id': test['id']}
+ ret = yield dbapi.db_find_one('reviews', query)
+ if ret:
+ test['voted'] = 'true'
+ else:
+ test['voted'] = 'false'
+
+ raise gen.Return({self.table: data})
+
@swagger.operation(nickname="createTest")
@web.asynchronous
def post(self):
@@ -111,6 +129,8 @@ class TestsCLHandler(GenericTestHandler):
self.finish_request({'code': '403', 'msg': msg})
return
+ if self.is_onap:
+ self.json_args['is_onap'] = 'true'
self._create(miss_fields=miss_fields, carriers=carriers)
@@ -149,7 +169,6 @@ class TestsGURHandler(GenericTestHandler):
raise gen.Return('API response validation enabled')
@swagger.operation(nickname="deleteTestById")
- @web.asynchronous
@gen.coroutine
def delete(self, test_id):
curr_user = self.get_secure_cookie(auth_const.OPENID)
@@ -161,6 +180,9 @@ class TestsGURHandler(GenericTestHandler):
raises.NotFound(message.not_found(self.table, query))
if curr_user == test_data['owner'] or \
curr_user_role.find('administrator') != -1:
+ yield dbapi.db_delete('applications',
+ {'test_id': test_data['id']})
+ yield dbapi.db_delete('reviews', {'test_id': test_data['id']})
self._delete(query=query)
else:
raises.Forbidden(message.no_auth())
@@ -198,7 +220,7 @@ class TestsGURHandler(GenericTestHandler):
if query and table:
data = yield dbapi.db_find_one(table, query)
if data:
- raise gen.Return((True, 'Data alreay exists. %s' % (query),
+ raise gen.Return((True, 'Data already exists. %s' % (query),
data.get("openid")))
raise gen.Return((False, 'Data does not exist. %s' % (query), None))
@@ -255,9 +277,9 @@ class TestsGURHandler(GenericTestHandler):
return
if item == "status":
- if value in {'approved', 'not approved'}:
+ if value == 'verified':
if test['status'] == 'private':
- msg = 'Not allowed to approve/not approve'
+ msg = 'Not allowed to verify'
self.finish_request({'code': 403, 'msg': msg})
return
@@ -272,7 +294,7 @@ class TestsGURHandler(GenericTestHandler):
self.finish_request({'code': 403, 'msg': msg})
return
- if not test['sut_label']:
+ if not self.is_onap and not test['sut_label']:
msg = 'Please fill out SUT version before submission'
self.finish_request({'code': 403, 'msg': msg})
return
@@ -284,8 +306,7 @@ class TestsGURHandler(GenericTestHandler):
'id': test['id'],
'$or': [
{'status': 'review'},
- {'status': 'approved'},
- {'status': 'not approved'}
+ {'status': 'verified'}
]
}
record = yield dbapi.db_find_one("tests", test_query)
@@ -311,12 +332,12 @@ class TestsGURHandler(GenericTestHandler):
logging.debug('check review')
query['user_id'] = user
data = yield dbapi.db_find_one('applications', query)
- if not data:
- logging.debug('not found')
+ if data:
+ logging.debug('results are bound to an application')
raise gen.Return((False, message.no_auth()))
- if value == "approve" or value == "not approved":
- logging.debug('check approve')
- query['role'] = {"$regex": ".*reviewer.*"}
+ if value == "verified":
+ logging.debug('check verify')
+ query['role'] = {"$regex": ".*administrator.*"}
query['openid'] = user
data = yield dbapi.db_find_one('users', query)
if not data: