def post(self): """add user""" user_profile = get_user(request=self.request) # checking level access to this ressource if not user_profile['role'] == constant.ROLE_ADMIN: raise HTTP_403("access refused") # checking query request login = self.request.data.get("login") if login is None: raise HTTP_400("login is expected") if not len(login): raise HTTP_400("login name cannot be empty") password = self.request.data.get("password") if password is None: raise HTTP_400("password is expected") if not len(password): raise HTTP_400("password name cannot be empty") role = self.request.data.get("role") if role not in constant.ROLE_LIST: raise HTTP_400("bad role provided") success, details = usersmanager.add_user(role=role, login=login, password=password) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "user successfully added"}
def post(self): """create session""" # checking query request login = self.request.data.get("login") if login is None: raise HTTP_400("login is expected") password = self.request.data.get("password") if password is None: raise HTTP_400("password is expected") # check user access auth_ret, u, sess_id = sessionsmanager.do_session_auth(login=login, password=password) if not auth_ret: raise HTTP_401("authentification failed") # set sessionid on cookie self.response.set_cookie(key="session_id", value=sess_id, expires='', path='/', domain="") _rsp = { "cmd": self.request.path, "message": "Logged in", "session_id": sess_id, "expires": settings.cfg["session"]["max-expiry-age"], "role": u[login]["role"], "api_login": login, "api_secret": u[login]['secrets']["basic"] } return _rsp
def get(self, file_path): """get files""" user_profile = _get_user(request=self.request) try: projectId = self.request.args.get("workspace", 1) file_path = fix_encoding_uri_param(file_path) except EmptyValue as e: raise HTTP_400("%s" % e) except Exception as e: raise HTTP_400("Invalid request provided (%s ?)" % e) _check_project_permissions( user_login=user_profile['login'], project_id=projectId) # avoid directory traversal file_path = os.path.normpath("/" + file_path) success, _, _, _, _, content, _, _= RepoTests.instance().getFile(pathFile=file_path, binaryMode=True, project=projectId, addLock=False, b64encode=True) if success != Context.instance().CODE_OK: raise HTTP_500("Unable to download file") return {"cmd": self.request.path, "file-content": content}
def patch(self, login): """update user""" user_profile = get_user(request=self.request) login = fix_encoding_uri_param(login) if user_profile['role'] != constant.ROLE_ADMIN: if user_profile["login"] != login: raise HTTP_403("access denied") cur_pwd = self.request.data.get("current-password") if cur_pwd is None: raise HTTP_400("Current password is expected") new_pwd = self.request.data.get("new-password") if new_pwd is None: raise HTTP_400("New password is expected") if not len(new_pwd): raise HTTP_400("password name cannot be empty") success, details = usersmanager.update_pwd(login=login, new_pwd=new_pwd, cur_pwd=cur_pwd) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "password successfully updated"}
def _assert_got_all_needed_tag_and_meta_ids(entity_type, tag_ids, meta_ids): expected_tag_ids = sorted(tag.id for tag in entity_type.tags if tag.delete_ts is None) expected_meta_ids = sorted(meta.id for meta in entity_type.meta if meta.delete_ts is None) if tag_ids != expected_tag_ids: raise HTTP_400('Expected tag IDs {}, got {}'.format( expected_tag_ids, tag_ids)) if meta_ids != expected_meta_ids: raise HTTP_400('Expected meta IDs {}, got {}'.format( expected_meta_ids, meta_ids))
def post(self, file_path): """upload file""" user_profile = _get_user(request=self.request) if user_profile['monitor']: raise HTTP_403("Access refused") try: projectId = self.request.args.get("workspace", 1) file_path = fix_encoding_uri_param(file_path) fileContent = self.request.data.get("file-content") if fileContent is None: raise EmptyValue("Please specify a file content") except EmptyValue as e: raise HTTP_400("%s" % e) except Exception as e: raise HTTP_400("Invalid request provided (%s ?)" % e) _check_project_permissions( user_login=user_profile['login'], project_id=projectId) try: filePath = os.path.normpath(file_path) p = pathlib.Path(filePath) fileExt = p.suffix[1:] fileName = p.stem filePath = filePath.rsplit("%s%s" %(p.stem, p.suffix))[0] except Exception as e: raise HTTP_403('Invalid file name: %s' % e) success, _, _, _, _, _, _, _, _ = RepoTests.instance().uploadFile(pathFile=filePath, nameFile=fileName, extFile=fileExt, contentFile=fileContent, login=user_profile['login'], project=projectId, overwriteFile=True, createFolders=True, lockMode=False, binaryMode=True) if success != Context.instance().CODE_OK: raise HTTP_500("Unable to upload file") return {"cmd": self.request.path, "message": "success"}
def post(self): """Add a new task""" user_profile = get_user(request=self.request) yaml_file = self.request.data.get("yaml-file") yaml_content = self.request.data.get("yaml-content") if yaml_file is None and yaml_content is None: raise EmptyValue("yaml content or file is expected") workspace = self.request.data.get("workspace", "common") sched_mode = self.request.data.get("mode", 0) sched_at = self.request.data.get("schedule-at", (0, 0, 0, 0, 0, 0) ) if sched_mode not in constant.SCHED_MODE: raise HTTP_400("invalid sched mode") success, details = jobsmanager.schedule_job( user=user_profile, job_descr=yaml_content, job_file=yaml_file, workspace=workspace, sched_mode=sched_mode, sched_at=sched_at, ) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "job successfully scheduled", "id": details}
def post(self): """ POST /user/login """ username = self.request.data.get('username') password = self.request.data.get('password') code2fa = self.request.data.get('code2fa') if c.cfg['2fa'] else None if not username or not password: raise HTTP_400( 'Yo dawg, you need to provide a username and password') if c.cfg['2fa'] and not code2fa: raise HTTP_400('Yo dawg, you need to provide a code2fa') try: data = api.UserLogin(username, password, code2fa) except: l.log_exception('api_ws.UserCheckPassword') if 'error' in data.keys(): raise HTTP_401(data['error']) self.response.set_header('Access-Control-Allow-Origin', '*') self.response.set_cookie("session_id", api.UserSetSession(username)) return data
def delete(self): vk_id = self.request.args.get('vk_id') tg_id = self.request.args.get('tg_id') if not (vk_id and tg_id): raise HTTP_400('Invalid `vk_id` or `tg_id` value') rpc_call('remove_connection', self.user['id'], vk_id, tg_id) self.response.status_code = 204 return ''
def post(self): vk_id = self.request.data.get('vk_id') tg_id = self.request.data.get('tg_id') active = int(self.request.data.get('active', 1)) if not (vk_id and tg_id): raise HTTP_400('Invalid `vk_id` or `tg_id` value') rpc_call('set_connection', self.user['id'], vk_id, tg_id, active) self.response.status_code = 204 return ''
def post(self): """Add a new project, only for administrator""" user_profile = get_user(request=self.request) # checking level access to this ressource if user_profile['role'] != constant.ROLE_ADMIN: raise HTTP_403("access refused") # checking request name = self.request.data.get("name") if name is None: raise HTTP_400("workspace name is mandatory") if not len(name): raise HTTP_400("workspace name cannot be empty") success, details = workspacesmanager.add_workspace(name=name) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "workspace successfully added", "project-id": details}
def post(self): username = self.request.data.get("username") password = self.request.data.get("password") if not username or not password: raise HTTP_400("Username and password are required") if username != "foo" or password != "foo": raise HTTP_401("Username or password are incorrect") # Set a session ID for lookup in a DB or memcache self.response.set_cookie("session_id", "1234567890abcdefg") return {"message": "Logged in"}
def get(self): """get executions""" user_profile = _get_user(request=self.request) try: projectId = self.request.args.get("workspace", 1) testId = self.request.args.get("id") if testId is None: raise HTTP_400("Please specify execution id") _log_index = self.request.args.get("log_index", 0) projectId = int(projectId) except EmptyValue as e: raise HTTP_400("%s" % e) except Exception as e: raise HTTP_400("Bad request provided (%s ?)" % e) _check_project_permissions(user_login=user_profile['login'], project_id=projectId) founded, testPath = RepoArchives.instance().findTrInCache(projectId=projectId, testId=testId) if founded == Context.instance().CODE_NOT_FOUND: raise HTTP_404('Test result not found') state = RepoArchives.instance().getTrState(trPath=testPath) verdict = RepoArchives.instance().getTrEndResult(trPath=testPath) logs, logs_index = RepoArchives.instance().getTrLogs(trPath=testPath, log_index=_log_index) return {"cmd": self.request.path, 'execution-id': testId, 'status': state, 'verdict': verdict, 'logs': logs, 'logs-index': logs_index}
def post(self): """ POST /user/setpassword """ username = self.request.data.get('username') password = self.request.data.get('password') if not username or not password: raise HTTP_400( 'Yo dawg, you need to provide a username and password') try: data = api.UserSetPassword(username, password) except: l.log_exception('api_ws.UserSetPassword') if 'error' in data.keys(): raise HTTP_401(data['error']) self.response.set_header('Access-Control-Allow-Origin', '*') self.response.set_cookie("session_id", api.UserSetSession(username)) return data
def post(self): """add globals entries""" workspace = self.request.args.get("workspace", "common") # checking query request var_value = self.request.data.get("value") if var_value is None: raise HTTP_400("Value is expected") success, details = globalsmanager.saves_entries(content=var_value, workspace=workspace) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "success",}
def _check_project_permissions(user_login, project_id): """ Look up project """ try: project_id = int(project_id) except BaseException: raise HTTP_400( "Invalid workspace id (Id=%s) provided in request, int expected" % str(project_id)) # get the project id according to the name and checking permissions project_authorized = ProjectsManager.instance().checkProjectsAuthorization(user=user_login, projectId=project_id) if not project_authorized: raise HTTP_403('Permission denied to this workspace')
def post(self): """ POST /user/setnewpassword """ username = api.UserSession(self.request) if not username: raise HTTP_401("I can't let you do that") old_password = self.request.data.get('old_password') new_password = self.request.data.get('new_password') if not old_password or not new_password: raise HTTP_400( 'Yo dawg, you need to provide a old_password and a new_password' ) try: data = api.UserSetNewPassword(username, old_password, new_password) except: l.log_exception('api_ws.UserSetNewPassword') if 'error' in data.keys(): raise HTTP_401(data['error']) self.response.set_header('Access-Control-Allow-Origin', '*') return data
def post(self): source = self.request.data.get("source") token = self.request.data.get("token") if source == None or token == None: raise HTTP_400("we need source and token") message = "this token is " ret = Database.findOne("tokens", {"source":source,"token":token}) retour = {} if ret != None: message += "valid" retour["is_valid"] = 1 retour["id"] = int(ret["source_id"]) else: message += "not valid" retour["is_valid"] = 0 retour["message"] = message return retour
def wrapped(*args, **kwargs): if not params: logger.warn("require_params decorator used without any parameters specified.") return f(*args, **kwargs) missing_params = [] # Iterate through required params to find if any are missing. for param in params: # Append all missing params to the list of missing params. if param not in args[0].request.data: missing_params.append(param) # If there were any missing parameters, return a descriptive error. if len(missing_params) > 0: logger.info('require_params decorator found missing parameters in request.') raise HTTP_400(f"Error, missing parameters: {', '.join(missing_params)}") return f(*args, **kwargs)
def post(self): username = self.request.data.get("username") password = self.request.data.get("password") if not username or not password: raise HTTP_400("Please specify username and password") # See if a user exists with those params user = db.query(User).filter( User.username==username, User.password==password).first() if not user: raise HTTP_401("Invalid username or password") # Create a new session sess = UserSession( user_id=user.id) db.add(sess) self.response.set_cookie("session_id", sess.session_id) return { "message":"Logged in", "session_id":sess.session_id }
def patch(self, login): """update user""" user_profile = get_user(request=self.request) # checking level access to this ressource if user_profile['role'] != constant.ROLE_ADMIN: raise HTTP_403("access refused") # checking query request login = fix_encoding_uri_param(login) role = self.request.data.get("role") if role not in constant.ROLE_LIST: raise HTTP_400("bad role provided") success, details = usersmanager.update_role(login=login, role=role) if success != constant.OK: raise HTTP_500(details) return {"cmd": self.request.path, "message": "role successfully updated"}
def post(self): source = self.request.data.get("source") source_id = self.request.data.get("id") limit_time = self.request.data.get("limit_time") if source == None or source_id == None or limit_time == None: raise HTTP_400("we need source, id and limit_time (0 = unlimited)") ret = Database.findOne("tokens", {"source_id":source_id, "source":source}) if ret != None: return {"message":"token already existe for this user", "token":str(ret["token"])} token = generate_token() while Database.findOne("tokens", {"token":token}) != None: token = generate_token() if int(limit_time) != 0: limit_time = int(time()) + int(limit_time) elem = { "token":token, "source":source, "source_id":source_id, "limit_time":limit_time } Database.insert("tokens", elem) return {"message":"new token is create", "token":str(token)}
def delete(self, file_path): """delete file""" user_profile = _get_user(request=self.request) if user_profile['monitor']: raise HTTP_403("Access refused") try: projectId = self.request.args.get("workspace", 1) file_path = fix_encoding_uri_param(file_path) except Exception as e: raise HTTP_400("Invalid request provided (%s ?)" % e) # avoid directory traversal filePath = os.path.normpath("/" + file_path) success = RepoTests.instance().delFile(pathFile=filePath, project=projectId, supportSnapshot=False) if success != Context.instance().CODE_OK: raise HTTP_500("Unable to delete file") return {"cmd": self.request.path, "message": "success"}
def post(self): """create job""" user_profile = _get_user(request=self.request) projectId = self.request.args.get("workspace", 1) try: yamlFile = self.request.data.get("yaml-file") if yamlFile is None: raise EmptyValue("Please specify a yaml file") yamlContent = self.request.data.get("yaml-content", "") scheduleId = self.request.data.get("schedule-id", 0) _scheduleAt = self.request.data.get("schedule-at") _scheduleRepeat = self.request.data.get("schedule-repeat", 0) _debugEnabled = self.request.data.get("debug-enabled") _fromTime = self.request.data.get("from-time") _toTime = self.request.data.get("to-time") _testInputs = self.request.data.get("file-parameters") projectId = int(projectId) scheduleId = int(scheduleId) except EmptyValue as e: raise HTTP_400("%s" % e) except Exception as e: raise HTTP_400("Invalid request provided (%s ?)" % e) # checking input if _testInputs is not None: if not isinstance(_testInputs, list): raise HTTP_400( "Invalid parameters provided in request, list expected") for inp in _testInputs: if not isinstance(inp, dict): raise HTTP_400( "Invalid parameters provided in request, list of dict expected") if not ("name" in inp and "type" in inp and "value" in inp): raise HTTP_400( "Invalid parameters provided in request") # run a test not save; change the project id to the default if projectId == 0: projectId = ProjectsManager.instance().getDefaultProjectForUser( user=user_profile['login']) _check_project_permissions( user_login=user_profile['login'], project_id=projectId) try: if yamlFile.startswith("//"): yamlFile = yamlFile[1:] yamlFile = os.path.normpath(yamlFile) p = pathlib.Path(yamlFile) fileExtension = p.suffix[1:] fileName = p.stem filePath = yamlFile.rsplit("%s%s" %(p.stem, p.suffix))[0] except Exception as e: raise HTTP_403('Invalid yaml file: %s' % e) if len(yamlContent): try: res = yaml.safe_load(yamlContent) except Exception as e: raise HTTP_403('Invalid yaml content: %s' % e) else: try: file_path = "%s/%s/%s/%s.%s" % (RepoTests.instance().testsPath, projectId, filePath, fileName, fileExtension) # read the file with open(file_path, "r") as f: doc_yaml = f.read() res = yaml.safe_load(doc_yaml) except Exception as e: raise HTTP_403('Invalid yaml file: %s' % e) try: # just for backward compatibility if "testplan" in res: testextension = "tpx" testfile = res["testplan"] elif "testglobal" in res: testextension = "tgx" testfile = res["testglobal"] elif "testsuite" in res: testextension = "tsx" elif "testunit" in res: testextension = "tux" # end of backward compatibility elif "python" in res: testextension = "tsx" elif "actions" in res: testextension = "tpx" testfile = res["actions"] else: raise Exception("invalid yaml format") # add default props if missing if "properties" not in res: res["properties"] = {} # add default descriptions if missing if "descriptions" not in res["properties"]: res["properties"]["descriptions"] = {} if "author" not in res["properties"]["descriptions"]: res["properties"]["descriptions"]["author"] = "undefined" if "name" not in res["properties"]["descriptions"]: res["properties"]["descriptions"]["name"] = "undefined" if "requirement" not in res["properties"]["descriptions"]: res["properties"]["descriptions"]["requirement"] = "undefined" if "summary" not in res["properties"]["descriptions"]: res["properties"]["descriptions"]["summary"] = "undefined" # add parameters if missing if "parameters" not in res["properties"]: res["properties"]["parameters"] = [] # add default scope in main parameters for p in res["properties"]["parameters"]: if "scope" not in p: p["scope"] = "local" if "value" not in p: p["value"] = "" if "type" not in p: if p["value"] is None: p["type"] = "none" p["value"] = "" elif isinstance(p["value"], bool): p["type"] = "bool" p["value"] = "%s" % p["value"] elif isinstance(p["value"], int): p["type"] = "int" p["value"] = "%s" % p["value"] elif isinstance(p["value"], list) or isinstance(p["value"], dict): p["type"] = "json" p["value"] = json.dumps(p["value"]) else: p["type"] = "text" testprops = {} testprops["inputs-parameters"] = {} testprops["inputs-parameters"]["parameter"] = res["properties"]["parameters"] testprops["descriptions"] = {} testprops["descriptions"]["description"] = [] for k,v in res["properties"]["descriptions"].items(): s = { 'key': k, 'value': v } testprops["descriptions"]["description"].append(s) if testextension in ["tpx", "tgx"]: doc = TestPlan.DataModel() testplan = {} testplan['testplan'] = { 'testfile': [] } i = 1 for tp in testfile: # add parameters if missing if "parameters" not in tp: tp["parameters"] = [] # add default scope in main parameters for p in tp["parameters"]: if "scope" not in p: p["scope"] = "local" if "value" not in p: p["value"] = "" if "type" not in p: if p["value"] is None: p["type"] = "none" p["value"] = "" elif isinstance(p["value"], bool): p["type"] = "bool" p["value"] = "%s" % p["value"] elif isinstance(p["value"], int): p["type"] = "int" p["value"] = "%s" % p["value"] elif isinstance(p["value"], list) or isinstance(p["value"], dict): p["type"] = "json" p["value"] = json.dumps(p["value"]) else: p["type"] = "text" if "id" not in tp: tp["id"] = "%s" % i if isinstance(tp["id"], int): tp["id"] = str(tp["id"]) if "parent" not in tp: tp["parent"] = "0" if isinstance(tp["parent"], int): tp["parent"] = str(tp["parent"]) if "parent-condition" not in tp: tp["parent-condition"] = "0" else: if tp["parent-condition"] == "success": tp["parent-condition"] = "0" else: tp["parent-condition"] = "1" tp["parent-condition"] = str(tp["parent-condition"]) if "description" in tp: tp["alias"] = tp["description"] i+=1 tf_descr = [ {"key": "author", "value": "undefined"}, {"key": "summary", "value": "undefined"}, {"key": "name", "value": "undefined"}, {"key": "requirement", "value": "undefined"}] tf_prop = {"properties": {"descriptions": { "description": tf_descr}, "inputs-parameters": {} }} tf_prop["properties"]["inputs-parameters"]["parameter"] = tp["parameters"] tp.update(tf_prop) testplan['testplan']['testfile'].append(tp) doc.testplan = testplan tests = doc.getSorted() if testextension == "tpx": success, error_msg = RepoTests.instance().addtf2tp(data_=tests) if success != Context.instance().CODE_OK: raise HTTP_500( 'Unable to prepare test plan: %s' % error_msg) else: success, error_msg, tests = RepoTests.instance().addtf2tg(data_=tests) if success != Context.instance().CODE_OK: raise HTTP_500( 'Unable to prepare test global: %s' % error_msg) testData = {'test-properties': testprops, 'test-extension': testextension} if testextension == "tsx": if "python" in res: testData['test-definition'] = res["python"] else: testData['test-definition'] = res["testsuite"] testData['test-execution'] = "" elif testextension == "tux": testData['test-definition'] = res["testunit"] else: testData['test-execution'] = tests except Exception as e: raise HTTP_500('Unable to decode yaml: %s' % e) # now we can create the task debugEnabled = False fromTime = (0, 0, 0, 0, 0, 0) toTime = (0, 0, 0, 0, 0, 0) message = "success" scheduleAt = (0, 0, 0, 0, 0, 0) if _debugEnabled is not None: debugEnabled = _debugEnabled if _fromTime is not None: fromTime = _fromTime if _toTime is not None: toTime = _toTime if _scheduleAt is not None: scheduleAt = _scheduleAt # personalize test description ? if _testInputs is not None: for newInp in _testInputs: if "scope" not in newInp: newInp["scope"] = "local" for origInp in testData["test-properties"]['inputs-parameters']['parameter']: if "scope" not in origInp: origInp["scope"] = "local" # if the param exist on the original test than overwrite # them if newInp["name"] == origInp["name"]: origInp["value"] = newInp["value"] origInp["type"] = newInp["type"] origInp["scope"] = newInp["scope"] if not filePath.endswith(fileName): if len(filePath): _testPath = "%s/%s" % (filePath, fileName) else: _testPath = fileName _testPath = os.path.normpath(_testPath) else: _testPath = filePath task = TaskManager.instance().registerTask( testData=testData, testName=fileName, testPath=_testPath, testUserId=user_profile['id'], testUser=user_profile['login'], testId=0, testBackground=True, runAt=scheduleAt, runType=scheduleId, runNb=_scheduleRepeat, withoutProbes=False, debugActivated=debugEnabled, withoutNotif=False, noKeepTr=False, testProjectId=projectId, runFrom=fromTime, runTo=toTime, stepByStep=False, breakpoint=False, channelId=False ) if task.lastError is not None: raise HTTP_500('ERROR: %s' % task.lastError) message = "success" if task.isRecursive(): message = "recursive" if task.isPostponed(): message = "postponed" if task.isSuccessive(): message = "successive" return {"cmd": self.request.path, "message": message, "job-id": task.getId(), "execution-id": task.getTestID()}
def post(self): phone = parse_phone(self.request.data.get('phone')) if phone == self.user['phone_number']: user = self.get() if user.get('authorized', True): return user code = self.request.data.get('code') password = self.request.data.get('password') phone_code_hash = None if not phone: raise HTTP_400('Invalid `phone` value') msg = None is_authorized = False try: client = TelegramClient( os.path.join(config.get('paths', 'sessions'), parse_phone(phone)), config.get('telegram', 'api_id'), config.get('telegram', 'api_hash')) if not client.is_connected(): client.connect() # check if already authorized if client.is_user_authorized(): self._set_authorized(phone) is_authorized = True raise AuthorizedSuccessfully() # 2nd step if code: t = db.get_interim_state(phone) if not t: raise HTTP_400('Invalid `phone` value') phone_code_hash = t['phone_code_hash'] resp = client.sign_in(phone, code, password=password, phone_code_hash=phone_code_hash) # 2nd/3rd step success if code and client.is_user_authorized(): self._set_authorized(phone) is_authorized = True raise AuthorizedSuccessfully() # 1st step if not resp.phone_registered: db.del_interim_state(phone) raise HTTP_400('Phone number is not registered') db.set_interim_state(phone, { 'provider': 'Telegram', 'phone_code_hash': resp.phone_code_hash }) return {'authorized': False, 'code': True} except AuthorizedSuccessfully: pass except SessionPasswordNeededError: return {'authorized': False, '2fa': True} except (PhoneNumberBannedError, PhoneNumberInvalidError, PhoneCodeExpiredError, PhoneCodeInvalidError, PhoneCodeEmptyError, PhonePasswordProtectedError) as e: db.del_interim_state(phone) client.log_out() raise HTTP_400(str(e)) except (FloodWaitError, FloodError, PhonePasswordFloodError) as e: db.del_interim_state(phone) raise HTTP_400(str(e)) except HTTPError: # passthru raise except Exception as e: self.logger.error('Telegram communication error %s', e) msg = str(e) raise finally: client.disconnect() if is_authorized: return self.get() raise HTTP_500('Internal error', msg)