From a82ee29bc7349bc2f0ed54cfc0ac83e7607cb1cc Mon Sep 17 00:00:00 2001 From: SerenaFeng Date: Fri, 27 Oct 2017 16:28:48 +0800 Subject: divide resources into handlers and models divide resources into handlers&models put ui handlers into handlers directory put User into user_models.py Change-Id: I3d9e260097205213c3ea8d4eac08b9019e017f71 Signed-off-by: SerenaFeng --- .../testapi/opnfv_testapi/handlers/__init__.py | 0 .../opnfv_testapi/handlers/base_handlers.py | 257 +++++++ .../testapi/opnfv_testapi/handlers/pod_handlers.py | 78 +++ .../opnfv_testapi/handlers/project_handlers.py | 86 +++ .../opnfv_testapi/handlers/result_handlers.py | 288 ++++++++ .../opnfv_testapi/handlers/root_handlers.py | 10 + .../opnfv_testapi/handlers/scenario_handlers.py | 775 +++++++++++++++++++++ .../opnfv_testapi/handlers/sign_handlers.py | 59 ++ .../opnfv_testapi/handlers/testcase_handlers.py | 103 +++ .../opnfv_testapi/handlers/user_handlers.py | 25 + 10 files changed, 1681 insertions(+) create mode 100644 utils/test/testapi/opnfv_testapi/handlers/__init__.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/base_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/project_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/result_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/root_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py create mode 100644 utils/test/testapi/opnfv_testapi/handlers/user_handlers.py (limited to 'utils/test/testapi/opnfv_testapi/handlers') diff --git a/utils/test/testapi/opnfv_testapi/handlers/__init__.py b/utils/test/testapi/opnfv_testapi/handlers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py new file mode 100644 index 000000000..a8ee3db2b --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py @@ -0,0 +1,257 @@ +############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.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 +# feng.xiaowei@zte.com.cn refactor db.pod to db.pods 5-19-2016 +# feng.xiaowei@zte.com.cn refactor test_project to project 5-19-2016 +# feng.xiaowei@zte.com.cn refactor response body 5-19-2016 +# feng.xiaowei@zte.com.cn refactor pod/project response info 5-19-2016 +# feng.xiaowei@zte.com.cn refactor testcase related handler 5-20-2016 +# feng.xiaowei@zte.com.cn refactor result related handler 5-23-2016 +# feng.xiaowei@zte.com.cn refactor dashboard related handler 5-24-2016 +# feng.xiaowei@zte.com.cn add methods to GenericApiHandler 5-26-2016 +# feng.xiaowei@zte.com.cn remove PodHandler 5-26-2016 +# feng.xiaowei@zte.com.cn remove ProjectHandler 5-26-2016 +# feng.xiaowei@zte.com.cn remove TestcaseHandler 5-27-2016 +# feng.xiaowei@zte.com.cn remove ResultHandler 5-29-2016 +# feng.xiaowei@zte.com.cn remove DashboardHandler 5-30-2016 +############################################################################## + +from datetime import datetime +import json + +from tornado import gen +from tornado import web + +from opnfv_testapi.common import check +from opnfv_testapi.common import message +from opnfv_testapi.common import raises +from opnfv_testapi.db import api as dbapi +from opnfv_testapi.models import base_models +from opnfv_testapi.tornado_swagger import swagger + +DEFAULT_REPRESENTATION = "application/json" + + +class GenericApiHandler(web.RequestHandler): + def __init__(self, application, request, **kwargs): + super(GenericApiHandler, self).__init__(application, request, **kwargs) + self.json_args = None + self.table = None + self.table_cls = None + self.db_projects = 'projects' + self.db_pods = 'pods' + self.db_testcases = 'testcases' + self.db_results = 'results' + self.db_scenarios = 'scenarios' + self.auth = self.settings["auth"] + + def prepare(self): + if self.request.body: + if self.request.headers.get("Content-Type") is not None: + if self.request.headers["Content-Type"].startswith( + DEFAULT_REPRESENTATION): + try: + self.json_args = json.loads(self.request.body) + except (ValueError, KeyError, TypeError) as error: + raises.BadRequest(message.bad_format(str(error))) + + def finish_request(self, json_object=None): + if json_object: + self.write(json.dumps(json_object)) + self.set_header("Content-Type", DEFAULT_REPRESENTATION) + self.finish() + + def _create_response(self, resource): + href = self.request.full_url() + '/' + str(resource) + return base_models.CreateResponse(href=href).format() + + def format_data(self, data): + cls_data = self.table_cls.from_dict(data) + return cls_data.format_http() + + @web.asynchronous + @gen.coroutine + @check.is_authorized + @check.valid_token + @check.no_body + @check.miss_fields + @check.values_check + @check.carriers_exist + @check.new_not_exists + def _create(self, **kwargs): + """ + :param miss_checks: [miss1, miss2] + :param db_checks: [(table, exist, query, error)] + """ + data = self.table_cls.from_dict(self.json_args) + for k, v in kwargs.iteritems(): + if k != 'query': + data.__setattr__(k, v) + + if self.table != 'results': + data.creation_date = datetime.now() + _id = yield dbapi.db_save(self.table, data.format()) + if 'name' in self.json_args: + resource = data.name + else: + resource = _id + self.finish_request(self._create_response(resource)) + + @web.asynchronous + @gen.coroutine + def _list(self, query=None, res_op=None, *args, **kwargs): + sort = kwargs.get('sort') + page = kwargs.get('page', 0) + last = kwargs.get('last', 0) + per_page = kwargs.get('per_page', 0) + if query is None: + query = {} + pipelines = list() + pipelines.append({'$match': query}) + + total_pages = 0 + data = list() + cursor = dbapi.db_list(self.table, query) + records_count = yield cursor.count() + if records_count > 0: + if page > 0: + total_pages, return_nr = self._calc_total_pages(records_count, + last, + page, + per_page) + pipelines = self._set_pipelines(pipelines, + sort, + return_nr, + page, + per_page) + cursor = dbapi.db_aggregate(self.table, pipelines) + while (yield cursor.fetch_next): + data.append(self.format_data(cursor.next_object())) + if res_op is None: + res = {self.table: data} + else: + res = res_op(data, *args) + if page > 0: + res.update({ + 'pagination': { + 'current_page': kwargs.get('page'), + 'total_pages': total_pages + } + }) + self.finish_request(res) + + @staticmethod + def _calc_total_pages(records_count, last, page, per_page): + records_nr = records_count + if (records_count > last) and (last > 0): + records_nr = last + + total_pages, remainder = divmod(records_nr, per_page) + if remainder > 0: + total_pages += 1 + if page > 1 and page > total_pages: + raises.BadRequest( + 'Request page > total_pages [{}]'.format(total_pages)) + return total_pages, records_nr + + @staticmethod + def _set_pipelines(pipelines, sort, return_nr, page, per_page): + if sort: + pipelines.append({'$sort': sort}) + + over = (page - 1) * per_page + left = return_nr - over + pipelines.append({'$skip': over}) + pipelines.append({'$limit': per_page if per_page < left else left}) + + return pipelines + + @web.asynchronous + @gen.coroutine + @check.not_exist + def _get_one(self, data, query=None): + self.finish_request(self.format_data(data)) + + @web.asynchronous + @gen.coroutine + @check.not_exist + def _delete(self, data, query=None): + yield dbapi.db_delete(self.table, query) + self.finish_request() + + @web.asynchronous + @gen.coroutine + @check.no_body + @check.not_exist + @check.updated_one_not_exist + def _update(self, data, query=None, **kwargs): + data = self.table_cls.from_dict(data) + update_req = self._update_requests(data) + yield dbapi.db_update(self.table, query, update_req) + update_req['_id'] = str(data._id) + self.finish_request(update_req) + + @web.asynchronous + @gen.coroutine + @check.no_body + @check.not_exist + @check.updated_one_not_exist + def pure_update(self, data, query=None, **kwargs): + data = self.table_cls.from_dict(data) + update_req = self._update_requests(data) + yield dbapi.db_update(self.table, query, update_req) + self.finish_request() + + def _update_requests(self, data): + request = dict() + for k, v in self.json_args.iteritems(): + request = self._update_request(request, k, v, + data.__getattribute__(k)) + if not request: + raises.Forbidden(message.no_update()) + + edit_request = data.format() + edit_request.update(request) + return edit_request + + @staticmethod + def _update_request(edit_request, key, new_value, old_value): + """ + This function serves to prepare the elements in the update request. + We try to avoid replace the exact values in the db + edit_request should be a dict in which we add an entry (key) after + comparing values + """ + if not (new_value is None): + if new_value != old_value: + edit_request[key] = new_value + + return edit_request + + def _update_query(self, keys, data): + query = dict() + equal = True + for key in keys: + new = self.json_args.get(key) + old = data.get(key) + if new is None: + new = old + elif new != old: + equal = False + query[key] = new + return query if not equal else dict() + + +class VersionHandler(GenericApiHandler): + @swagger.operation(nickname='listAllVersions') + def get(self): + """ + @description: list all supported versions + @rtype: L{Versions} + """ + versions = [{'version': 'v1.0', 'description': 'basics'}] + self.finish_request({'versions': versions}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py new file mode 100644 index 000000000..abf5bf9f1 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py @@ -0,0 +1,78 @@ +############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.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 opnfv_testapi.handlers import base_handlers +from opnfv_testapi.models import pod_models +from opnfv_testapi.tornado_swagger import swagger + + +class GenericPodHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericPodHandler, self).__init__(application, request, **kwargs) + self.table = 'pods' + self.table_cls = pod_models.Pod + + +class PodCLHandler(GenericPodHandler): + @swagger.operation(nickname='listAllPods') + def get(self): + """ + @description: list all pods + @return 200: list all pods, empty list is no pod exist + @rtype: L{Pods} + """ + self._list() + + @swagger.operation(nickname='createPod') + def post(self): + """ + @description: create a pod + @param body: pod to be created + @type body: L{PodCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: pod is created. + @raise 403: pod already exists + @raise 400: body or name not provided + """ + def query(): + return {'name': self.json_args.get('name')} + miss_fields = ['name'] + self._create(miss_fields=miss_fields, query=query) + + +class PodGURHandler(GenericPodHandler): + @swagger.operation(nickname='getPodByName') + def get(self, pod_name): + """ + @description: get a single pod by pod_name + @rtype: L{Pod} + @return 200: pod exist + @raise 404: pod not exist + """ + self._get_one(query={'name': pod_name}) + + def delete(self, pod_name): + """ Remove a POD + + # check for an existing pod to be deleted + mongo_dict = yield self.db.pods.find_one( + {'name': pod_name}) + pod = TestProject.pod(mongo_dict) + if pod is None: + raise HTTPError(HTTP_NOT_FOUND, + "{} could not be found as a pod to be deleted" + .format(pod_name)) + + # just delete it, or maybe save it elsewhere in a future + res = yield self.db.projects.remove( + {'name': pod_name}) + + self.finish_request(answer) + """ + pass diff --git a/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py new file mode 100644 index 000000000..30d9ab34a --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py @@ -0,0 +1,86 @@ +############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.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 opnfv_testapi.handlers import base_handlers +from opnfv_testapi.models import project_models +from opnfv_testapi.tornado_swagger import swagger + + +class GenericProjectHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericProjectHandler, self).__init__(application, + request, + **kwargs) + self.table = 'projects' + self.table_cls = project_models.Project + + +class ProjectCLHandler(GenericProjectHandler): + @swagger.operation(nickname="listAllProjects") + def get(self): + """ + @description: list all projects + @return 200: return all projects, empty list is no project exist + @rtype: L{Projects} + """ + self._list() + + @swagger.operation(nickname="createProject") + def post(self): + """ + @description: create a project + @param body: project to be created + @type body: L{ProjectCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: project is created. + @raise 403: project already exists + @raise 400: body or name not provided + """ + def query(): + return {'name': self.json_args.get('name')} + miss_fields = ['name'] + self._create(miss_fields=miss_fields, query=query) + + +class ProjectGURHandler(GenericProjectHandler): + @swagger.operation(nickname='getProjectByName') + def get(self, project_name): + """ + @description: get a single project by project_name + @rtype: L{Project} + @return 200: project exist + @raise 404: project not exist + """ + self._get_one(query={'name': project_name}) + + @swagger.operation(nickname="updateProjectByName") + def put(self, project_name): + """ + @description: update a single project by project_name + @param body: project to be updated + @type body: L{ProjectUpdateRequest} + @in body: body + @rtype: L{Project} + @return 200: update success + @raise 404: project not exist + @raise 403: new project name already exist or nothing to update + """ + query = {'name': project_name} + db_keys = ['name'] + self._update(query=query, db_keys=db_keys) + + @swagger.operation(nickname='deleteProjectByName') + def delete(self, project_name): + """ + @description: delete a project by project_name + @return 200: delete success + @raise 404: project not exist + """ + self._delete(query={'name': project_name}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py new file mode 100644 index 000000000..c4b61ff22 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py @@ -0,0 +1,288 @@ +############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.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 +from datetime import timedelta +import json +import logging + +from bson import objectid + +from opnfv_testapi.common import constants +from opnfv_testapi.common import message +from opnfv_testapi.common import raises +from opnfv_testapi.common.config import CONF +from opnfv_testapi.handlers import base_handlers +from opnfv_testapi.models import result_models +from opnfv_testapi.tornado_swagger import swagger + + +class GenericResultHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericResultHandler, self).__init__(application, + request, + **kwargs) + self.table = self.db_results + self.table_cls = result_models.TestResult + + def get_int(self, key, value): + try: + value = int(value) + except Exception: + raises.BadRequest(message.must_int(key)) + return value + + def set_query(self): + query = dict() + date_range = dict() + + query['public'] = {'$not': {'$eq': 'false'}} + for k in self.request.query_arguments.keys(): + v = self.get_query_argument(k) + if k == 'project' or k == 'pod' or k == 'case': + query[k + '_name'] = v + elif k == 'period': + v = self.get_int(k, v) + if v > 0: + period = datetime.now() - timedelta(days=v) + obj = {"$gte": str(period)} + query['start_date'] = obj + elif k == 'trust_indicator': + query[k + '.current'] = float(v) + elif k == 'from': + date_range.update({'$gte': str(v)}) + elif k == 'to': + date_range.update({'$lt': str(v)}) + elif k == 'signed': + username = self.get_secure_cookie(constants.TESTAPI_ID) + role = self.get_secure_cookie(constants.ROLE) + if role: + del query['public'] + if role != "reviewer": + query['user'] = username + elif k not in ['last', 'page', 'descend']: + query[k] = v + if date_range: + query['start_date'] = date_range + + # if $lt is not provided, + # empty/None/null/'' start_date will also be returned + if 'start_date' in query and '$lt' not in query['start_date']: + query['start_date'].update({'$lt': str(datetime.now())}) + + return query + + +class ResultsCLHandler(GenericResultHandler): + @swagger.operation(nickname="queryTestResults") + def get(self): + """ + @description: Retrieve result(s) for a test project + on a specific pod. + @notes: Retrieve result(s) for a test project on a specific pod. + Available filters for this request are : + - project : project name + - case : case name + - pod : pod name + - version : platform version (Arno-R1, ...) + - installer : fuel/apex/compass/joid/daisy + - build_tag : Jenkins build tag name + - period : x last days, incompatible with from/to + - from : starting time in 2016-01-01 or 2016-01-01 00:01:23 + - to : ending time in 2016-01-01 or 2016-01-01 00:01:23 + - scenario : the test scenario (previously version) + - criteria : the global criteria status passed or failed + - trust_indicator : evaluate the stability of the test case + to avoid running systematically long and stable test case + - signed : get logined user result + + GET /results/project=functest&case=vPing&version=Arno-R1 \ + &pod=pod_name&period=15&signed + @return 200: all test results consist with query, + empty list if no result is found + @rtype: L{TestResults} + @param pod: pod name + @type pod: L{string} + @in pod: query + @required pod: False + @param project: project name + @type project: L{string} + @in project: query + @required project: False + @param case: case name + @type case: L{string} + @in case: query + @required case: False + @param version: i.e. Colorado + @type version: L{string} + @in version: query + @required version: False + @param installer: fuel/apex/joid/compass + @type installer: L{string} + @in installer: query + @required installer: False + @param build_tag: i.e. v3.0 + @type build_tag: L{string} + @in build_tag: query + @required build_tag: False + @param scenario: i.e. odl + @type scenario: L{string} + @in scenario: query + @required scenario: False + @param criteria: i.e. passed + @type criteria: L{string} + @in criteria: query + @required criteria: False + @param period: last days + @type period: L{string} + @in period: query + @required period: False + @param from: i.e. 2016-01-01 or 2016-01-01 00:01:23 + @type from: L{string} + @in from: query + @required from: False + @param to: i.e. 2016-01-01 or 2016-01-01 00:01:23 + @type to: L{string} + @in to: query + @required to: False + @param last: last records stored until now + @type last: L{string} + @in last: query + @required last: False + @param page: which page to list, default to 1 + @type page: L{int} + @in page: query + @required page: False + @param trust_indicator: must be float + @type trust_indicator: L{float} + @in trust_indicator: query + @required trust_indicator: False + @param signed: user results or all results + @type signed: L{string} + @in signed: query + @required signed: False + @param descend: true, newest2oldest; false, oldest2newest + @type descend: L{string} + @in descend: query + @required descend: False + """ + 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', 1)) + + limitations = { + 'sort': {'_id': descend_limit()}, + 'last': last_limit(), + 'page': page_limit(), + 'per_page': CONF.api_results_per_page + } + + self._list(query=self.set_query(), **limitations) + + @swagger.operation(nickname="createTestResult") + def post(self): + """ + @description: create a test result + @param body: result to be created + @type body: L{ResultCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: result is created. + @raise 404: pod/project/testcase not exist + @raise 400: body/pod_name/project_name/case_name not provided + """ + self._post() + + def _post(self): + def pod_query(): + return {'name': self.json_args.get('pod_name')} + + def project_query(): + return {'name': self.json_args.get('project_name')} + + def testcase_query(): + return {'project_name': self.json_args.get('project_name'), + 'name': self.json_args.get('case_name')} + + def options_check(field, options): + return self.json_args.get(field).upper() in options + + miss_fields = ['pod_name', 'project_name', 'case_name'] + carriers = [('pods', pod_query), + ('projects', project_query), + ('testcases', testcase_query)] + values_check = [('criteria', options_check, ['PASS', 'FAIL'])] + + self._create(miss_fields=miss_fields, + carriers=carriers, + values_check=values_check) + + +class ResultsUploadHandler(ResultsCLHandler): + @swagger.operation(nickname="uploadTestResult") + def post(self): + """ + @description: upload and create a test result + @param body: result to be created + @type body: L{ResultCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: result is created. + @raise 404: pod/project/testcase not exist + @raise 400: body/pod_name/project_name/case_name not provided + """ + logging.info('file upload') + fileinfo = self.request.files['file'][0] + is_public = self.get_body_argument('public') + logging.warning('public:%s', is_public) + logging.info('results is :%s', fileinfo['filename']) + logging.info('results is :%s', fileinfo['body']) + self.json_args = json.loads(fileinfo['body']).copy() + self.json_args['public'] = is_public + + openid = self.get_secure_cookie(constants.TESTAPI_ID) + if openid: + self.json_args['user'] = openid + + super(ResultsUploadHandler, self)._post() + + +class ResultsGURHandler(GenericResultHandler): + @swagger.operation(nickname='getTestResultById') + def get(self, result_id): + """ + @description: get a single result by result_id + @rtype: L{TestResult} + @return 200: test result exist + @raise 404: test result not exist + """ + query = dict() + query["_id"] = objectid.ObjectId(result_id) + self._get_one(query=query) + + @swagger.operation(nickname="updateTestResultById") + def put(self, result_id): + """ + @description: update a single result by _id + @param body: fields to be updated + @type body: L{ResultUpdateRequest} + @in body: body + @rtype: L{Result} + @return 200: update success + @raise 404: result not exist + @raise 403: nothing to update + """ + query = {'_id': objectid.ObjectId(result_id)} + db_keys = [] + self._update(query=query, db_keys=db_keys) diff --git a/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py new file mode 100644 index 000000000..92920fa85 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py @@ -0,0 +1,10 @@ +from opnfv_testapi.common.config import CONF +from opnfv_testapi.handlers import base_handlers + + +class RootHandler(base_handlers.GenericApiHandler): + def get_template_path(self): + return CONF.ui_static_path + + def get(self): + self.render('testapi-ui/index.html') diff --git a/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py new file mode 100644 index 000000000..67abcfff6 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py @@ -0,0 +1,775 @@ +import functools + +from opnfv_testapi.common import message +from opnfv_testapi.common import raises +from opnfv_testapi.handlers import base_handlers +import opnfv_testapi.models.scenario_models as models +from opnfv_testapi.tornado_swagger import swagger + + +class GenericScenarioHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericScenarioHandler, self).__init__(application, + request, + **kwargs) + self.table = self.db_scenarios + self.table_cls = models.Scenario + + def set_query(self, locators): + query = dict() + elem_query = dict() + for k, v in locators.iteritems(): + if k == 'scenario': + query['name'] = v + elif k == 'installer': + elem_query["installer"] = v + elif k == 'version': + elem_query["versions.version"] = v + elif k == 'project': + elem_query["versions.projects.project"] = v + else: + query[k] = v + if elem_query: + query['installers'] = {'$elemMatch': elem_query} + return query + + +class ScenariosCLHandler(GenericScenarioHandler): + @swagger.operation(nickname="queryScenarios") + def get(self): + """ + @description: Retrieve scenario(s). + @notes: Retrieve scenario(s) + Available filters for this request are : + - name : scenario name + + GET /scenarios?name=scenario_1 + @param name: scenario name + @type name: L{string} + @in name: query + @required name: False + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: False + @param version: version + @type version: L{string} + @in version: query + @required version: False + @param project: project name + @type project: L{string} + @in project: query + @required project: False + @return 200: all scenarios satisfy queries, + empty list if no scenario is found + @rtype: L{Scenarios} + """ + + def _set_query(): + query = dict() + elem_query = dict() + for k in self.request.query_arguments.keys(): + v = self.get_query_argument(k) + if k == 'installer': + elem_query["installer"] = v + elif k == 'version': + elem_query["versions.version"] = v + elif k == 'project': + elem_query["versions.projects.project"] = v + else: + query[k] = v + if elem_query: + query['installers'] = {'$elemMatch': elem_query} + return query + + self._list(query=_set_query()) + + @swagger.operation(nickname="createScenario") + def post(self): + """ + @description: create a new scenario by name + @param body: scenario to be created + @type body: L{ScenarioCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: scenario is created. + @raise 403: scenario already exists + @raise 400: body or name not provided + """ + def query(): + return {'name': self.json_args.get('name')} + miss_fields = ['name'] + self._create(miss_fields=miss_fields, query=query) + + +class ScenarioGURHandler(GenericScenarioHandler): + @swagger.operation(nickname='getScenarioByName') + def get(self, name): + """ + @description: get a single scenario by name + @rtype: L{Scenario} + @return 200: scenario exist + @raise 404: scenario not exist + """ + self._get_one(query={'name': name}) + pass + + @swagger.operation(nickname="updateScenarioName") + def put(self, name): + """ + @description: update scenario, only rename is supported currently + @param body: fields to be updated + @type body: L{ScenarioUpdateRequest} + @in body: body + @rtype: L{Scenario} + @return 200: update success + @raise 404: scenario not exist + @raise 403: nothing to update + """ + query = {'name': name} + db_keys = ['name'] + self._update(query=query, db_keys=db_keys) + + @swagger.operation(nickname="deleteScenarioByName") + def delete(self, name): + """ + @description: delete a scenario by name + @return 200: delete success + @raise 404: scenario not exist: + """ + self._delete(query={'name': name}) + + +class ScenarioUpdater(object): + def __init__(self, data, body=None, + installer=None, version=None, project=None): + self.data = data + self.body = body + self.installer = installer + self.version = version + self.project = project + + def update(self, item, action): + updates = { + ('scores', 'post'): self._update_requests_add_score, + ('trust_indicators', 'post'): self._update_requests_add_ti, + ('customs', 'post'): self._update_requests_add_customs, + ('customs', 'put'): self._update_requests_update_customs, + ('customs', 'delete'): self._update_requests_delete_customs, + ('projects', 'post'): self._update_requests_add_projects, + ('projects', 'put'): self._update_requests_update_projects, + ('projects', 'delete'): self._update_requests_delete_projects, + ('owner', 'put'): self._update_requests_change_owner, + ('versions', 'post'): self._update_requests_add_versions, + ('versions', 'put'): self._update_requests_update_versions, + ('versions', 'delete'): self._update_requests_delete_versions, + ('installers', 'post'): self._update_requests_add_installers, + ('installers', 'put'): self._update_requests_update_installers, + ('installers', 'delete'): self._update_requests_delete_installers, + } + updates[(item, action)](self.data) + + return self.data.format() + + def iter_installers(xstep): + @functools.wraps(xstep) + def magic(self, data): + [xstep(self, installer) + for installer in self._filter_installers(data.installers)] + return magic + + def iter_versions(xstep): + @functools.wraps(xstep) + def magic(self, installer): + [xstep(self, version) + for version in (self._filter_versions(installer.versions))] + return magic + + def iter_projects(xstep): + @functools.wraps(xstep) + def magic(self, version): + [xstep(self, project) + for project in (self._filter_projects(version.projects))] + return magic + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_add_score(self, project): + project.scores.append( + models.ScenarioScore.from_dict(self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_add_ti(self, project): + project.trust_indicators.append( + models.ScenarioTI.from_dict(self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_add_customs(self, project): + project.customs = list(set(project.customs + self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_update_customs(self, project): + project.customs = list(set(self.body)) + + @iter_installers + @iter_versions + @iter_projects + def _update_requests_delete_customs(self, project): + project.customs = filter( + lambda f: f not in self.body, + project.customs) + + @iter_installers + @iter_versions + def _update_requests_add_projects(self, version): + version.projects = self._update_with_body(models.ScenarioProject, + 'project', + version.projects) + + @iter_installers + @iter_versions + def _update_requests_update_projects(self, version): + version.projects = self._update_with_body(models.ScenarioProject, + 'project', + list()) + + @iter_installers + @iter_versions + def _update_requests_delete_projects(self, version): + version.projects = self._remove_projects(version.projects) + + @iter_installers + @iter_versions + def _update_requests_change_owner(self, version): + version.owner = self.body.get('owner') + + @iter_installers + def _update_requests_add_versions(self, installer): + installer.versions = self._update_with_body(models.ScenarioVersion, + 'version', + installer.versions) + + @iter_installers + def _update_requests_update_versions(self, installer): + installer.versions = self._update_with_body(models.ScenarioVersion, + 'version', + list()) + + @iter_installers + def _update_requests_delete_versions(self, installer): + installer.versions = self._remove_versions(installer.versions) + + def _update_requests_add_installers(self, scenario): + scenario.installers = self._update_with_body(models.ScenarioInstaller, + 'installer', + scenario.installers) + + def _update_requests_update_installers(self, scenario): + scenario.installers = self._update_with_body(models.ScenarioInstaller, + 'installer', + list()) + + def _update_requests_delete_installers(self, scenario): + scenario.installers = self._remove_installers(scenario.installers) + + def _update_with_body(self, clazz, field, withs): + exists = list() + malformat = list() + for new in self.body: + try: + format_new = clazz.from_dict_with_raise(new) + new_name = getattr(format_new, field) + if not any(getattr(o, field) == new_name for o in withs): + withs.append(format_new) + else: + exists.append(new_name) + except Exception as error: + malformat.append(error.message) + if malformat: + raises.BadRequest(message.bad_format(malformat)) + elif exists: + raises.Conflict(message.exist('{}s'.format(field), exists)) + return withs + + def _filter_installers(self, installers): + return self._filter('installer', installers) + + def _remove_installers(self, installers): + return self._remove('installer', installers) + + def _filter_versions(self, versions): + return self._filter('version', versions) + + def _remove_versions(self, versions): + return self._remove('version', versions) + + def _filter_projects(self, projects): + return self._filter('project', projects) + + def _remove_projects(self, projects): + return self._remove('project', projects) + + def _filter(self, item, items): + return filter( + lambda f: getattr(f, item) == getattr(self, item), + items) + + def _remove(self, field, fields): + return filter( + lambda f: getattr(f, field) not in self.body, + fields) + + +class GenericScenarioUpdateHandler(GenericScenarioHandler): + def __init__(self, application, request, **kwargs): + super(GenericScenarioUpdateHandler, self).__init__(application, + request, + **kwargs) + self.installer = None + self.version = None + self.project = None + self.item = None + self.action = None + + def do_update(self, item, action, locators): + self.item = item + self.action = action + for k, v in locators.iteritems(): + if not v: + v = self.get_query_argument(k) + setattr(self, k, v) + locators[k] = v + self.pure_update(query=self.set_query(locators=locators)) + + def _update_requests(self, data): + return ScenarioUpdater(data, + self.json_args, + self.installer, + self.version, + self.project).update(self.item, self.action) + + +class ScenarioScoresHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addScoreRecord") + def post(self, scenario): + """ + @description: add a new score record + @notes: add a new score record to a project + POST /api/v1/scenarios//scores? \ + installer=& \ + version=& \ + project= + @param body: score to be added + @type body: L{ScenarioScore} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: score is created. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('scores', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + +class ScenarioTIsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addTrustIndicatorRecord") + def post(self, scenario): + """ + @description: add a new trust indicator record + @notes: add a new trust indicator record to a project + POST /api/v1/scenarios//trust_indicators? \ + installer=& \ + version=& \ + project= + @param body: trust indicator to be added + @type body: L{ScenarioTI} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: trust indicator is added. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('trust_indicators', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + +class ScenarioCustomsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addCustomizedTestCases") + def post(self, scenario): + """ + @description: add customized test cases + @notes: add several test cases to a project + POST /api/v1/scenarios//customs? \ + installer=& \ + version=& \ + project= + @param body: test cases to be added + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: test cases are added. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + @swagger.operation(nickname="updateCustomizedTestCases") + def put(self, scenario): + """ + @description: update customized test cases + @notes: substitute all the customized test cases + PUT /api/v1/scenarios//customs? \ + installer=& \ + version=& \ + project= + @param body: new supported test cases + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: substitute test cases success. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + @swagger.operation(nickname="deleteCustomizedTestCases") + def delete(self, scenario): + """ + @description: delete one or several customized test cases + @notes: delete one or some customized test cases + DELETE /api/v1/scenarios//customs? \ + installer=& \ + version=& \ + project= + @param body: test case(s) to be deleted + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @param project: project name + @type project: L{string} + @in project: query + @required project: True + @return 200: delete test case(s) success. + @raise 404: scenario/installer/version/project not existed + """ + self.do_update('customs', + 'delete', + locators={'scenario': scenario, + 'installer': None, + 'version': None, + 'project': None}) + + +class ScenarioProjectsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addProjectsUnderScenario") + def post(self, scenario): + """ + @description: add projects to scenario + @notes: add one or multiple projects + POST /api/v1/scenarios//projects? \ + installer=& \ + version= + @param body: projects to be added + @type body: C{list} of L{ScenarioProject} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: projects are added. + @raise 400: bad schema + @raise 409: conflict, project already exists + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'post', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + @swagger.operation(nickname="updateScenarioProjects") + def put(self, scenario): + """ + @description: replace all projects + @notes: substitute all projects, delete existed ones with new provides + PUT /api/v1/scenarios//projects? \ + installer=& \ + version= + @param body: new projects + @type body: C{list} of L{ScenarioProject} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: replace projects success. + @raise 400: bad schema + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + @swagger.operation(nickname="deleteProjectsUnderScenario") + def delete(self, scenario): + """ + @description: delete one or multiple projects + @notes: delete one or multiple projects + DELETE /api/v1/scenarios//projects? \ + installer=& \ + version= + @param body: projects(names) to be deleted + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: delete project(s) success. + @raise 404: scenario/installer/version not existed + """ + self.do_update('projects', + 'delete', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + +class ScenarioOwnerHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="changeScenarioOwner") + def put(self, scenario): + """ + @description: change scenario owner + @notes: substitute all projects, delete existed ones with new provides + PUT /api/v1/scenarios//owner? \ + installer=& \ + version= + @param body: new owner + @type body: L{ScenarioChangeOwnerRequest} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @param version: version + @type version: L{string} + @in version: query + @required version: True + @return 200: change owner success. + @raise 404: scenario/installer/version not existed + """ + self.do_update('owner', + 'put', + locators={'scenario': scenario, + 'installer': None, + 'version': None}) + + +class ScenarioVersionsHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addVersionsUnderScenario") + def post(self, scenario): + """ + @description: add versions to scenario + @notes: add one or multiple versions + POST /api/v1/scenarios//versions? \ + installer= + @param body: versions to be added + @type body: C{list} of L{ScenarioVersion} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @return 200: versions are added. + @raise 400: bad schema + @raise 409: conflict, version already exists + @raise 404: scenario/installer not exist + """ + self.do_update('versions', + 'post', + locators={'scenario': scenario, + 'installer': None}) + + @swagger.operation(nickname="updateVersionsUnderScenario") + def put(self, scenario): + """ + @description: replace all versions + @notes: substitute all versions as a totality + PUT /api/v1/scenarios//versions? \ + installer= + @param body: new versions + @type body: C{list} of L{ScenarioVersion} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @return 200: replace versions success. + @raise 400: bad schema + @raise 404: scenario/installer not exist + """ + self.do_update('versions', + 'put', + locators={'scenario': scenario, + 'installer': None}) + + @swagger.operation(nickname="deleteVersionsUnderScenario") + def delete(self, scenario): + """ + @description: delete one or multiple versions + @notes: delete one or multiple versions + DELETE /api/v1/scenarios//versions? \ + installer= + @param body: versions(names) to be deleted + @type body: C{list} of L{string} + @in body: body + @param installer: installer type + @type installer: L{string} + @in installer: query + @required installer: True + @return 200: delete versions success. + @raise 404: scenario/installer not exist + """ + self.do_update('versions', + 'delete', + locators={'scenario': scenario, + 'installer': None}) + + +class ScenarioInstallersHandler(GenericScenarioUpdateHandler): + @swagger.operation(nickname="addInstallersUnderScenario") + def post(self, scenario): + """ + @description: add installers to scenario + @notes: add one or multiple installers + POST /api/v1/scenarios//installers + @param body: installers to be added + @type body: C{list} of L{ScenarioInstaller} + @in body: body + @return 200: installers are added. + @raise 400: bad schema + @raise 409: conflict, installer already exists + @raise 404: scenario not exist + """ + self.do_update('installers', + 'post', + locators={'scenario': scenario}) + + @swagger.operation(nickname="updateInstallersUnderScenario") + def put(self, scenario): + """ + @description: replace all installers + @notes: substitute all installers as a totality + PUT /api/v1/scenarios//installers + @param body: new installers + @type body: C{list} of L{ScenarioInstaller} + @in body: body + @return 200: replace versions success. + @raise 400: bad schema + @raise 404: scenario/installer not exist + """ + self.do_update('installers', + 'put', + locators={'scenario': scenario}) + + @swagger.operation(nickname="deleteInstallersUnderScenario") + def delete(self, scenario): + """ + @description: delete one or multiple installers + @notes: delete one or multiple installers + DELETE /api/v1/scenarios//installers + @param body: installers(names) to be deleted + @type body: C{list} of L{string} + @in body: body + @return 200: delete versions success. + @raise 404: scenario/installer not exist + """ + self.do_update('installers', + 'delete', + locators={'scenario': scenario}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py new file mode 100644 index 000000000..754066256 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py @@ -0,0 +1,59 @@ +from cas import CASClient +from tornado import gen +from tornado import web + +from opnfv_testapi.common import constants +from opnfv_testapi.common.config import CONF +from opnfv_testapi.db import api as dbapi +from opnfv_testapi.handlers import base_handlers + + +class SignBaseHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(SignBaseHandler, self).__init__(application, request, **kwargs) + self.table = 'users' + self.cas_client = CASClient(version='2', + server_url=CONF.lfid_cas_url, + service_url='{}/{}'.format( + CONF.ui_url, + CONF.lfid_signin_return)) + + +class SigninHandler(SignBaseHandler): + def get(self): + self.redirect(url=(self.cas_client.get_login_url())) + + +class SigninReturnHandler(SignBaseHandler): + + @web.asynchronous + @gen.coroutine + def get(self): + ticket = self.get_query_argument('ticket', default=None) + if ticket: + (user, attrs, _) = self.cas_client.verify_ticket(ticket=ticket) + login_user = { + 'user': user, + 'email': attrs.get('mail'), + 'fullname': attrs.get('field_lf_full_name'), + 'groups': constants.TESTAPI_USERS + attrs.get('group', []) + } + q_user = {'user': user} + db_user = yield dbapi.db_find_one(self.table, q_user) + if not db_user: + dbapi.db_save(self.table, login_user) + else: + dbapi.db_update(self.table, q_user, login_user) + + self.clear_cookie(constants.TESTAPI_ID) + self.set_secure_cookie(constants.TESTAPI_ID, user) + + self.redirect(url=CONF.ui_url) + + +class SignoutHandler(SignBaseHandler): + def get(self): + """Handle signout request.""" + self.clear_cookie(constants.TESTAPI_ID) + logout_url = self.cas_client.get_logout_url(redirect_url=CONF.ui_url) + self.redirect(url=logout_url) diff --git a/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py new file mode 100644 index 000000000..c4c3c21f5 --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py @@ -0,0 +1,103 @@ +############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.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 opnfv_testapi.handlers import base_handlers +from opnfv_testapi.models import testcase_models +from opnfv_testapi.tornado_swagger import swagger + + +class GenericTestcaseHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericTestcaseHandler, self).__init__(application, + request, + **kwargs) + self.table = self.db_testcases + self.table_cls = testcase_models.Testcase + + +class TestcaseCLHandler(GenericTestcaseHandler): + @swagger.operation(nickname="listAllTestCases") + def get(self, project_name): + """ + @description: list all testcases of a project by project_name + @return 200: return all testcases of this project, + empty list is no testcase exist in this project + @rtype: L{TestCases} + """ + self._list(query={'project_name': project_name}) + + @swagger.operation(nickname="createTestCase") + def post(self, project_name): + """ + @description: create a testcase of a project by project_name + @param body: testcase to be created + @type body: L{TestcaseCreateRequest} + @in body: body + @rtype: L{CreateResponse} + @return 200: testcase is created in this project. + @raise 403: project not exist + or testcase already exists in this project + @raise 400: body or name not provided + """ + def project_query(): + return {'name': project_name} + + def testcase_query(): + return {'project_name': project_name, + 'name': self.json_args.get('name')} + miss_fields = ['name'] + carriers = [(self.db_projects, project_query)] + self._create(miss_fields=miss_fields, + carriers=carriers, + query=testcase_query, + project_name=project_name) + + +class TestcaseGURHandler(GenericTestcaseHandler): + @swagger.operation(nickname='getTestCaseByName') + def get(self, project_name, case_name): + """ + @description: get a single testcase + by case_name and project_name + @rtype: L{Testcase} + @return 200: testcase exist + @raise 404: testcase not exist + """ + query = dict() + query['project_name'] = project_name + query["name"] = case_name + self._get_one(query=query) + + @swagger.operation(nickname="updateTestCaseByName") + def put(self, project_name, case_name): + """ + @description: update a single testcase + by project_name and case_name + @param body: testcase to be updated + @type body: L{TestcaseUpdateRequest} + @in body: body + @rtype: L{Project} + @return 200: update success + @raise 404: testcase or project not exist + @raise 403: new testcase name already exist in project + or nothing to update + """ + query = {'project_name': project_name, 'name': case_name} + db_keys = ['name', 'project_name'] + self._update(query=query, db_keys=db_keys) + + @swagger.operation(nickname='deleteTestCaseByName') + def delete(self, project_name, case_name): + """ + @description: delete a testcase by project_name and case_name + @return 200: delete success + @raise 404: testcase not exist + """ + query = {'project_name': project_name, 'name': case_name} + self._delete(query=query) diff --git a/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py new file mode 100644 index 000000000..5067e358b --- /dev/null +++ b/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py @@ -0,0 +1,25 @@ +from opnfv_testapi.common import constants +from opnfv_testapi.common import raises +from opnfv_testapi.common.config import CONF +from opnfv_testapi.handlers import base_handlers +from opnfv_testapi.models.user_models import User + + +class UserHandler(base_handlers.GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(UserHandler, self).__init__(application, request, **kwargs) + self.table = 'users' + self.table_cls = User + + def get(self): + if CONF.api_authenticate: + username = self.get_secure_cookie(constants.TESTAPI_ID) + if username: + self._get_one(query={'user': username}) + else: + raises.Unauthorized('Unauthorized') + else: + self.finish_request(User('anonymous', + 'anonymous@linuxfoundation.com', + 'anonymous lf', + constants.TESTAPI_USERS).format()) -- cgit 1.2.3-korg