def checkPasswordToken(self,session): """ Checks the password token if its valid arguments: session -- (Session) object from flask return the reponse object with a error code and a message """ requestFields = RequestDictionary(self.request) if(not requestFields.exists("token")): exc = ResponseException("Request body must include token", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) token = requestFields.getValue("token") success,message,errorCode = sesEmail.checkToken(token,self.interfaces.userDb,"password_reset") if(success): #mark session that password can be filled out LoginSession.resetPassword(session) return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"}) else: #failure but alert UI of issue return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
def checkEmailConfirmationToken(self,session): """ Creates user record and email arguments: session -- (Session) object from flask return the reponse object with a error code and a message """ requestFields = RequestDictionary(self.request) if(not requestFields.exists("token")): exc = ResponseException("Request body must include token", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) token = requestFields.getValue("token") success,message,errorCode = sesEmail.checkToken(token,self.interfaces.userDb,"validate_email") if(success): #mark session that email can be filled out LoginSession.register(session) #remove token so it cant be used again # The following line is commented out for issues with registration email links bouncing users back # to the original email input page instead of the registration page #self.interfaces.userDb.deleteToken(token) #set the status only if current status is awaiting confirmation user = self.interfaces.userDb.getUserByEmail(message) if self.interfaces.userDb.checkStatus(user,"awaiting_confirmation"): self.interfaces.userDb.changeStatus(user,"email_confirmed") return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"}) else: #failure but alert UI of issue return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
def checkPasswordToken(self,session): """ Checks the password token if its valid arguments: session -- (Session) object from flask return the reponse object with a error code and a message """ request_fields = RequestDictionary.derive(self.request) try: if 'token' not in request_fields: raise ResponseException( "Request body must include token", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc, exc.status) token = request_fields['token'] # Save token to be deleted after reset session["token"] = token success, message, errorCode = sesEmail.check_token(token, "password_reset") if success: #mark session that password can be filled out LoginSession.reset_password(session) return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"}) else: #failure but alert UI of issue return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
def test_max_login_success(monkeypatch): ah = accountHandler.AccountHandler(Mock()) mock_dict = Mock() mock_dict.return_value.safeDictionary.side_effect = {'ticket': '', 'service': ''} monkeypatch.setattr(accountHandler, 'RequestDictionary', mock_dict) max_dict = {'cas:serviceResponse': {}} monkeypatch.setattr(accountHandler, 'get_max_dict', Mock(return_value=max_dict)) config = {'parent_group': 'parent-group'} monkeypatch.setattr(accountHandler, 'CONFIG_BROKER', config) max_dict = make_max_dict('parent-group,parent-group-CGAC_SYS') monkeypatch.setattr(accountHandler, 'get_max_dict', Mock(return_value=max_dict)) # If it gets to this point, that means the user was in all the right groups aka successful login monkeypatch.setattr(ah, 'create_session_and_response', Mock(return_value=JsonResponse.create(StatusCode.OK, {"message": "Login successful"}))) json_response = ah.max_login(Mock()) assert "Login successful" == json.loads(json_response.get_data().decode("utf-8"))['message'] max_dict = make_max_dict('') monkeypatch.setattr(accountHandler, 'get_max_dict', Mock(return_value=max_dict)) # If it gets to this point, that means the user was in all the right groups aka successful login monkeypatch.setattr(ah, 'create_session_and_response', Mock(return_value=JsonResponse.create(StatusCode.OK, {"message": "Login successful"}))) json_response = ah.max_login(Mock()) assert "Login successful" == json.loads(json_response.get_data().decode("utf-8"))['message']
def find_existing_submissions_in_period(cgac_code, frec_code, reporting_fiscal_year, reporting_fiscal_period, submission_id=None): """ Find all the submissions in the given period for the given CGAC or FREC code Args: cgac_code: the CGAC code to check against or None if checking a FREC agency frec_code: the FREC code to check against or None if checking a CGAC agency reporting_fiscal_year: the year to check for reporting_fiscal_period: the period in the year to check for submission_id: the submission ID to check against (used when checking if this submission is being re-certified) Returns: A JsonResponse containing a success message to indicate there are no existing submissions in the given period or the error if there was one """ # We need either a cgac or a frec code for this function if not cgac_code and not frec_code: return JsonResponse.error(ValueError("CGAC or FR Entity Code required"), StatusCode.CLIENT_ERROR) submission_query = get_existing_submission_list(cgac_code, frec_code, reporting_fiscal_year, reporting_fiscal_period, submission_id) if submission_query.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submission_query[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def checkPasswordToken(self, session): """ Checks the password token if its valid arguments: session -- (Session) object from flask return the reponse object with a error code and a message """ requestFields = RequestDictionary(self.request) if (not requestFields.exists("token")): exc = ResponseException("Request body must include token", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) token = requestFields.getValue("token") success, message, errorCode = sesEmail.checkToken( token, self.interfaces.userDb, "password_reset") if (success): #mark session that password can be filled out LoginSession.resetPassword(session) return JsonResponse.create(StatusCode.OK, { "email": message, "errorCode": errorCode, "message": "success" }) else: #failure but alert UI of issue return JsonResponse.create(StatusCode.OK, { "errorCode": errorCode, "message": message })
def inner(*args, **kwargs): if g.user is None: return JsonResponse.create(StatusCode.LOGIN_REQUIRED, {'message': "Login Required"}) if not g.user.website_admin: return JsonResponse.create(StatusCode.LOGIN_REQUIRED, {'message': NOT_AUTHORIZED_MSG}) return func(*args, **kwargs)
def getProtectedFiles(self): """ Returns a set of urls to protected files on the help page """ response = {} if self.isLocal: response["urls"] = {} return JsonResponse.create(StatusCode.CLIENT_ERROR, response) response["urls"] = self.s3manager.getFileUrls(bucket_name=CONFIG_BROKER["static_files_bucket"], path=CONFIG_BROKER["help_files_path"]) return JsonResponse.create(StatusCode.OK, response)
def inner(*args, **kwargs): if g.user is None: return JsonResponse.create(StatusCode.LOGIN_REQUIRED, {'message': "Login Required"}) if not g.user.website_admin: return JsonResponse.create(StatusCode.LOGIN_REQUIRED, {'message': NOT_AUTHORIZED_MSG}) return func(*args, **kwargs)
def test_max_login_success_cert_login(monkeypatch): ah = account_handler.AccountHandler(Mock()) mock_dict = Mock() mock_dict.return_value.exists.return_value = True mock_dict.return_value.safeDictionary.side_effect = {'cert': ''} monkeypatch.setattr(account_handler, 'RequestDictionary', mock_dict) max_dict = {'cas:serviceResponse': {}} monkeypatch.setattr(account_handler, 'get_max_dict', Mock(return_value=max_dict)) config = { 'parent_group': 'parent-group', 'full_url': 'full-url', 'max_cert_url': 'max-cert-url' } monkeypatch.setattr(account_handler, 'CONFIG_BROKER', config) max_dict = make_max_dict('parent-group,parent-group-CGAC_SYS') max_dict['cas:serviceResponse']['cas:authenticationSuccess'][ 'cas:attributes']['maxAttribute:MAX-ID'] = 'S_id' monkeypatch.setattr(account_handler, 'get_max_dict', Mock(return_value=max_dict)) mock_resp = Mock() mock_resp.return_value = mock_response(url='ticket=12345') monkeypatch.setattr('requests.get', mock_resp) # If it gets to this point, that means the user was in all the right groups aka successful login monkeypatch.setattr( ah, 'create_session_and_response', Mock(return_value=JsonResponse.create( StatusCode.OK, {"message": "Login successful"}))) json_response = ah.max_login(Mock()) assert "Login successful" == json.loads( json_response.get_data().decode("utf-8"))['message'] max_dict = make_max_dict('') monkeypatch.setattr(account_handler, 'get_max_dict', Mock(return_value=max_dict)) # If it gets to this point, that means the user was in all the right groups aka successful login monkeypatch.setattr( ah, 'create_session_and_response', Mock(return_value=JsonResponse.create( StatusCode.OK, {"message": "Login successful"}))) json_response = ah.max_login(Mock()) assert "Login successful" == json.loads( json_response.get_data().decode("utf-8"))['message']
def find_existing_submissions_in_period(cgac_code, frec_code, reporting_fiscal_year, reporting_fiscal_period, submission_id=None): """ Find all the submissions in the given period for the given CGAC or FREC code Args: cgac_code: the CGAC code to check against or None if checking a FREC agency frec_code: the FREC code to check against or None if checking a CGAC agency reporting_fiscal_year: the year to check for reporting_fiscal_period: the period in the year to check for submission_id: the submission ID to check against (used when checking if this submission is being re-certified) Returns: A JsonResponse containing a success message to indicate there are no existing submissions in the given period or the error if there was one """ # We need either a cgac or a frec code for this function if not cgac_code and not frec_code: return JsonResponse.error( ValueError("CGAC or FR Entity Code required"), StatusCode.CLIENT_ERROR) sess = GlobalDB.db().session submission_query = sess.query(Submission).filter( (Submission.cgac_code == cgac_code) if cgac_code else (Submission.frec_code == frec_code), Submission.reporting_fiscal_year == reporting_fiscal_year, Submission.reporting_fiscal_period == reporting_fiscal_period, Submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']) # Filter out the submission we are potentially re-certifying if one is provided if submission_id: submission_query = submission_query.filter( Submission.submission_id != submission_id) submission_query = submission_query.order_by(desc(Submission.created_at)) if submission_query.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submission_query[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def set_new_password(self, session): """ Set a new password for a user, request should have keys "user_email" and "password" """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) required = ('user_email', 'password') try: if any(field not in request_dict for field in required): # Don't have the keys we need in request raise ResponseException( "Set password route requires keys user_email and password", StatusCode.CLIENT_ERROR ) if not self.checkPassword(request_dict['password']): raise ResponseException( "Invalid Password", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc,exc.status) # Get user from email user = sess.query(User).filter( func.lower(User.email) == func.lower(request_dict["user_email"]) ).one() # Set new password set_user_password(user,request_dict["password"],self.bcrypt) # Invalidate token oldToken = sess.query(EmailToken).filter(EmailToken.token == session["token"]).one() sess.delete(oldToken) sess.commit() session["reset"] = None # Return success message return JsonResponse.create(StatusCode.OK,{"message":"Password successfully changed"})
def list_users_with_status(self): """ List all users with the specified status. Associated request body must have key 'status' """ request_dict = RequestDictionary.derive(self.request) try: if 'status' not in request_dict: # Missing a required field, return 400 raise ResponseException( "Request body must include status", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc, exc.status) sess = GlobalDB.db().session try: users = sess.query(User).filter_by( user_status_id=USER_STATUS_DICT[request_dict['status']] ).all() except ValueError as exc: # Client provided a bad status return JsonResponse.error(exc, StatusCode.CLIENT_ERROR) user_info = [] for user in users: agency_name = sess.query(CGAC.agency_name).\ filter(CGAC.cgac_code == user.cgac_code).\ one_or_none() this_info = {"name":user.name, "title":user.title, "agency_name":agency_name, "cgac_code":user.cgac_code, "email":user.email, "id":user.user_id } user_info.append(this_info) return JsonResponse.create(StatusCode.OK,{"users":user_info})
def list_users(self): """ List all users ordered by status. Associated request body must have key 'filter_by' """ request_dict = RequestDictionary.derive( self.request, optional_request=True) user_status = request_dict.get('status', 'all') sess = GlobalDB.db().session try: user_query = sess.query(User) if user_status != "all": user_query = user_query.filter(User.user_status_id == USER_STATUS_DICT[user_status]) users = user_query.all() except ValueError as exc: # Client provided a bad status return JsonResponse.error(exc, StatusCode.CLIENT_ERROR) user_info = [] for user in users: agency_name = sess.query(CGAC.agency_name).\ filter(CGAC.cgac_code == user.cgac_code).\ one_or_none() thisInfo = {"name":user.name, "title":user.title, "agency_name":agency_name, "cgac_code":user.cgac_code, "email":user.email, "id":user.user_id, "is_active":user.is_active, "permission": PERMISSION_TYPE_DICT_ID.get(user.permission_type_id), "status": user.user_status.name} user_info.append(thisInfo) return JsonResponse.create(StatusCode.OK,{"users":user_info})
def list_all_agencies(): sess = GlobalDB.db().session cgacs = sess.query(CGAC).all() agency_list = [{'agency_name': cgac.agency_name, 'cgac_code': cgac.cgac_code} for cgac in cgacs] frecs = sess.query(FREC).all() shared_list = [{'agency_name': frec.agency_name, 'frec_code': frec.frec_code} for frec in frecs] return JsonResponse.create(StatusCode.OK, {'agency_list': agency_list, 'shared_agency_list': shared_list})
def resetPassword(self, system_email, session): """ Remove old password and email user a token to set a new password. Request should have key "email" arguments: system_email -- (string) email used to send messages session -- (Session) object from flask """ requestDict = RequestDictionary(self.request) if (not (requestDict.exists("email"))): # Don't have the keys we need in request exc = ResponseException( "Reset password route requires key 'email'", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Get user object try: user = self.interfaces.userDb.getUserByEmail( requestDict.getValue("email")) except Exception as e: exc = ResponseException("Unknown Error", StatusCode.CLIENT_ERROR, ValueError) return JsonResponse.error(exc, exc.status) email = requestDict.getValue("email") LoginSession.logout(session) self.sendResetPasswordEmail(user, system_email, email) # Return success message return JsonResponse.create(StatusCode.OK, {"message": "Password reset"})
def checkGeneration(self, submission_id = None, file_type = None): """ Return information about file generation jobs Returns: Response object with keys status, file_type, url, message. If file_type is D1 or D2, also includes start and end. """ if submission_id is None or file_type is None: submission_id, file_type = self.getRequestParamsForGenerate() # Check permission to submission self.checkSubmissionById(submission_id, file_type) uploadJob = self.interfaces.jobDb.getJobBySubmissionFileTypeAndJobType(submission_id, self.fileTypeMap[file_type], "file_upload") if file_type in ["D1","D2"]: validationJob = self.interfaces.jobDb.getJobBySubmissionFileTypeAndJobType(submission_id, self.fileTypeMap[file_type], "csv_record_validation") else: validationJob = None responseDict = {} responseDict["status"] = self.mapGenerateStatus(uploadJob, validationJob) responseDict["file_type"] = file_type responseDict["message"] = uploadJob.error_message or "" if uploadJob.filename is None: responseDict["url"] = "#" elif CONFIG_BROKER["use_aws"]: path, file_name = uploadJob.filename.split("/") responseDict["url"] = s3UrlHandler().getSignedUrl(path=path, fileName=file_name, bucketRoute=None, method="GET") else: responseDict["url"] = uploadJob.filename # Pull start and end from jobs table if D1 or D2 if file_type in ["D1","D2"]: responseDict["start"] = uploadJob.start_date.strftime("%m/%d/%Y") if uploadJob.start_date is not None else "" responseDict["end"] = uploadJob.end_date.strftime("%m/%d/%Y") if uploadJob.end_date is not None else "" return JsonResponse.create(StatusCode.OK,responseDict)
def list_sub_tier_agencies(sub_tier_agencies): """ List all Sub-Tier Agencies user has FABS permissions for Args: sub_tier_agencies - List of all SubTierAgencies generated by the get_fabs_sub_tier_agencies decorator, required to list only sub_tier_agencies that user has FABS permissions for """ return JsonResponse.create(StatusCode.OK, organize_sub_tier_agencies(sub_tier_agencies))
def getCurrentUser(self, session): """ Gets the current user information arguments: session -- (Session) object from flask return the reponse object with the current user information """ uid = session["name"] user = self.interfaces.userDb.getUserByUID(uid) permissionList = [] for permission in self.interfaces.userDb.getPermissionList(): if (self.interfaces.userDb.hasPermission(user, permission.name)): permissionList.append(permission.permission_type_id) agency_name = self.interfaces.validationDb.getAgencyName( user.cgac_code) return JsonResponse.create( StatusCode.OK, { "user_id": int(uid), "name": user.name, "agency_name": agency_name, "cgac_code": user.cgac_code, "title": user.title, "permissions": permissionList, "skip_guide": user.skip_guide })
def validate_job(self, request): """ Gets file for job, validates each row, and sends valid rows to a staging table Args: request -- HTTP request containing the jobId Returns: Http response object """ # Create connection to job tracker database sess = GlobalDB.db().session requestDict = RequestDictionary(request) if requestDict.exists('job_id'): job_id = requestDict.getValue('job_id') else: # Request does not have a job ID, can't validate validation_error_type = ValidationError.jobError raise ResponseException('No job ID specified in request', StatusCode.CLIENT_ERROR, None, validation_error_type) # Get the job job = sess.query(Job).filter_by(job_id=job_id).one_or_none() if job is None: validation_error_type = ValidationError.jobError writeFileError(job_id, None, validation_error_type) raise ResponseException( 'Job ID {} not found in database'.format(job_id), StatusCode.CLIENT_ERROR, None, validation_error_type) # Make sure job's prerequisites are complete if not run_job_checks(job_id): validation_error_type = ValidationError.jobError writeFileError(job_id, None, validation_error_type) raise ResponseException( 'Prerequisites for Job ID {} are not complete'.format(job_id), StatusCode.CLIENT_ERROR, None, validation_error_type) # Make sure this is a validation job if job.job_type.name in ('csv_record_validation', 'validation'): job_type_name = job.job_type.name else: validation_error_type = ValidationError.jobError writeFileError(job_id, None, validation_error_type) raise ResponseException( 'Job ID {} is not a validation job (job type is {})'.format( job_id, job.job_type.name), StatusCode.CLIENT_ERROR, None, validation_error_type) # set job status to running and do validations mark_job_status(job_id, "running") if job_type_name == 'csv_record_validation': self.runValidation(job) elif job_type_name == 'validation': self.runCrossValidation(job) else: raise ResponseException("Bad job type for validator", StatusCode.INTERNAL_ERROR) return JsonResponse.create(StatusCode.OK, {"message": "Validation complete"})
def listUsersWithStatus(self): """ List all users with the specified status. Associated request body must have key 'status' """ requestDict = RequestDictionary(self.request) if(not (requestDict.exists("status"))): # Missing a required field, return 400 exc = ResponseException("Request body must include status", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) current_user = self.interfaces.userDb.getUserByUID(flaskSession["name"]) try: if self.interfaces.userDb.hasPermission(current_user, "agency_admin"): users = self.interfaces.userDb.getUsersByStatus(requestDict.getValue("status"), current_user.cgac_code) else: users = self.interfaces.userDb.getUsersByStatus(requestDict.getValue("status")) except ValueError as e: # Client provided a bad status exc = ResponseException(str(e),StatusCode.CLIENT_ERROR,ValueError) return JsonResponse.error(exc,exc.status) userInfo = [] for user in users: agency_name = self.interfaces.validationDb.getAgencyName(user.cgac_code) thisInfo = {"name":user.name, "title":user.title, "agency_name":agency_name, "cgac_code":user.cgac_code, "email":user.email, "id":user.user_id } userInfo.append(thisInfo) return JsonResponse.create(StatusCode.OK,{"users":userInfo})
def list_all_agencies(): """ List all CGAC and FREC Agencies """ sess = GlobalDB.db().session agency_list, shared_list = [], [] # combine CGAC SubTierAgencies and CGACs without SubTierAgencies into the agency_list csubs = sess.query(SubTierAgency).filter( SubTierAgency.is_frec.is_(False)).distinct( SubTierAgency.cgac_id).all() all_cgacs = get_cgacs_without_sub_tier_agencies(sess) + [ st.cgac for st in csubs if st.is_frec is False ] agency_list = [{ 'agency_name': cst.agency_name, 'cgac_code': cst.cgac_code } for cst in all_cgacs] # add distinct FRECs from SubTierAgencies with a True is_frec into the shared_list fsubs = sess.query(SubTierAgency).filter( SubTierAgency.is_frec.is_(True)).distinct( SubTierAgency.frec_id).all() shared_list = [{ 'agency_name': fst.frec.agency_name, 'frec_code': fst.frec.frec_code } for fst in fsubs] return JsonResponse.create(StatusCode.OK, { 'agency_list': agency_list, 'shared_agency_list': shared_list })
def validate_threaded(): """Start the validation process on a new thread.""" @copy_current_request_context def ThreadedFunction(arg): """The new thread.""" threadedManager = ValidationManager(local, error_report_path) threadedManager.threadedValidateJob(arg) try: interfaces = InterfaceHolder() jobTracker = interfaces.jobDb except ResponseException as e: open("errorLog","a").write(str(e) + "\n") return JsonResponse.error(e,e.status,table = "cannot connect to job database") except Exception as e: open("errorLog","a").write(str(e) + "\n") exc = ResponseException(str(e),StatusCode.INTERNAL_ERROR,type(e)) return JsonResponse.error(exc,exc.status,table= "cannot connect to job database") jobId = None manager = ValidationManager(local, error_report_path) try: jobId = manager.getJobID(request) except ResponseException as e: manager.markJob(jobId,jobTracker,"invalid",interfaces.errorDb,manager.filename) CloudLogger.logError(str(e),e,traceback.extract_tb(sys.exc_info()[2])) return JsonResponse.error(e,e.status,table ="") except Exception as e: exc = ResponseException(str(e),StatusCode.CLIENT_ERROR,type(e)) manager.markJob(jobId,jobTracker,"invalid",interfaces.errorDb,manager.filename) CloudLogger.logError(str(e),exc,traceback.extract_tb(sys.exc_info()[2])) return JsonResponse.error(exc,exc.status,table="") try: manager.testJobID(jobId,interfaces) except ResponseException as e: open("errorLog","a").write(str(e) + "\n") # Job is not ready to run according to job tracker, do not change status of job in job tracker interfaces.errorDb.writeFileError(jobId,manager.filename,ValidationError.jobError) return JsonResponse.error(e,e.status,table="") except Exception as e: open("errorLog","a").write(str(e) + "\n") exc = ResponseException(str(e),StatusCode.CLIENT_ERROR,type(e)) interfaces.errorDb.writeFileError(jobId,manager.filename,ValidationError.jobError) return JsonResponse.error(exc,exc.status,table="") thread = Thread(target=ThreadedFunction, args= (jobId,)) try : jobTracker.markJobStatus(jobId,"running") except Exception as e: open("errorLog","a").write(str(e) + "\n") exc = ResponseException(str(e),StatusCode.INTERNAL_ERROR,type(e)) return JsonResponse.error(exc,exc.status,table="could not start job") interfaces.close() thread.start() return JsonResponse.create(StatusCode.OK,{"table":"job"+str(jobId)})
def resetPassword(self,system_email,session): """ Remove old password and email user a token to set a new password. Request should have key "email" arguments: system_email -- (string) email used to send messages session -- (Session) object from flask """ requestDict = RequestDictionary(self.request) if(not (requestDict.exists("email"))): # Don't have the keys we need in request exc = ResponseException("Reset password route requires key 'email'",StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) # Get user object try: user = self.interfaces.userDb.getUserByEmail(requestDict.getValue("email")) except Exception as e: exc = ResponseException("Unknown Error",StatusCode.CLIENT_ERROR,ValueError) return JsonResponse.error(exc,exc.status) email = requestDict.getValue("email") LoginSession.logout(session) self.sendResetPasswordEmail(user, system_email, email) # Return success message return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
def reset_password(self,system_email,session): """ Remove old password and email user a token to set a new password. Request should have key "email" arguments: system_email -- (string) email used to send messages session -- (Session) object from flask """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) try: if 'email' not in request_dict: # Don't have the keys we need in request raise ResponseException( "Reset password route requires key 'email'", StatusCode.CLIENT_ERROR ) user = sess.query(User).filter( func.lower(User.email) == func.lower(request_dict['email']) ).one() except Exception as exc: return JsonResponse.error(exc, StatusCode.CLIENT_ERROR) email = request_dict['email'] LoginSession.logout(session) self.send_reset_password_email(user, system_email, email) # Return success message return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
def setSkipGuide(self, session): """ Set current user's skip guide parameter """ uid = session["name"] userDb = self.interfaces.userDb user = userDb.getUserByUID(uid) requestDict = RequestDictionary(self.request) if not requestDict.exists("skip_guide"): exc = ResponseException("Must include skip_guide parameter", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) skipGuide = requestDict.getValue("skip_guide") if type(skipGuide) == type(True): # param is a bool user.skip_guide = skipGuide elif type(skipGuide) == type("string"): # param is a string, allow "true" or "false" if skipGuide.lower() == "true": user.skip_guide = True elif skipGuide.lower() == "false": user.skip_guide = False else: exc = ResponseException("skip_guide must be true or false", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) else: exc = ResponseException("skip_guide must be a boolean", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) userDb.session.commit() return JsonResponse.create(StatusCode.OK, { "message": "skip_guide set successfully", "skip_guide": skipGuide })
def setNewPassword(self, session): """ Set a new password for a user, request should have keys "user_email" and "password" """ requestDict = RequestDictionary(self.request) if (not (requestDict.exists("user_email") and requestDict.exists("password"))): # Don't have the keys we need in request exc = ResponseException( "Set password route requires keys user_email and password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) if (not self.checkPassword(requestDict.getValue("password"))): exc = ResponseException("Invalid Password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Get user from email user = self.interfaces.userDb.getUserByEmail( requestDict.getValue("user_email")) # Set new password self.interfaces.userDb.setPassword(user, requestDict.getValue("password"), self.bcrypt) # Invalidate token self.interfaces.userDb.deleteToken(session["token"]) session["reset"] = None # Return success message return JsonResponse.create( StatusCode.OK, {"message": "Password successfully changed"})
def list_agencies(cgac_sub_tiers, frec_sub_tiers): """ List all CGAC and FREC Agencies user has DABS permissions for Args: cgac_sub_tiers - List of all CGAC SubTierAgencies generated by the get_dabs_sub_tier_agencies decorator, required to list only sub_tier_agencies that user has DABS permissions for frec_sub_tiers - List of all FREC SubTierAgencies generated by the get_dabs_sub_tier_agencies decorator, required to list only sub_tier_agencies that user has DABS permissions for """ # combine SubTierAgency CGACs with CGACs without SubTierAgencies into a cgac_list all_cgacs = [st.cgac for st in cgac_sub_tiers if st.is_frec is False ] + get_cgacs_without_sub_tier_agencies() cgac_list = [{ 'agency_name': cst.agency_name, 'cgac_code': cst.cgac_code } for cst in all_cgacs] # convert the list of frec sub_tier_agencies into a list of frec agencies frec_list = [{ 'agency_name': fst.frec.agency_name, 'frec_code': fst.frec.frec_code } for fst in frec_sub_tiers] return JsonResponse.create(StatusCode.OK, { 'cgac_agency_list': cgac_list, 'frec_agency_list': frec_list })
def setSkipGuide(self, session): """ Set current user's skip guide parameter """ uid = session["name"] userDb = self.interfaces.userDb user = userDb.getUserByUID(uid) requestDict = RequestDictionary(self.request) if not requestDict.exists("skip_guide"): exc = ResponseException("Must include skip_guide parameter", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) skipGuide = requestDict.getValue("skip_guide") if type(skipGuide) == type(True): # param is a bool user.skip_guide = skipGuide elif type(skipGuide) == type("string"): # param is a string, allow "true" or "false" if skipGuide.lower() == "true": user.skip_guide = True elif skipGuide.lower() == "false": user.skip_guide = False else: exc = ResponseException("skip_guide must be true or false", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) else: exc = ResponseException("skip_guide must be a boolean", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) userDb.session.commit() return JsonResponse.create(StatusCode.OK,{"message":"skip_guide set successfully","skip_guide":skipGuide})
def set_skip_guide(self): """ Set current user's skip guide parameter Returns: JsonResponse object containing results of setting the skip guide or details of the error that occurred. Possible errors include the request not containing a skip_guide parameter or it not being a boolean value """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) try: if 'skip_guide' not in request_dict: raise ResponseException( "Must include skip_guide parameter", StatusCode.CLIENT_ERROR ) skip_guide = str(request_dict['skip_guide']).lower() if skip_guide not in ("true", "false"): raise ResponseException( "skip_guide must be true or false", StatusCode.CLIENT_ERROR ) g.user.skip_guide = skip_guide == "true" except ResponseException as exc: return JsonResponse.error(exc, exc.status) sess.commit() return JsonResponse.create(StatusCode.OK, {"message": "skip_guide set successfully", "skip_guide": skip_guide})
def listUsersWithStatus(self): """ List all users with the specified status. Associated request body must have key 'status' """ requestDict = RequestDictionary(self.request) if (not (requestDict.exists("status"))): # Missing a required field, return 400 exc = ResponseException("Request body must include status", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) try: users = self.interfaces.userDb.getUsersByStatus( requestDict.getValue("status")) except ValueError as e: # Client provided a bad status exc = ResponseException(str(e), StatusCode.CLIENT_ERROR, ValueError) return JsonResponse.error(exc, exc.status) userInfo = [] for user in users: thisInfo = { "name": user.name, "title": user.title, "agency": user.agency, "email": user.email, "id": user.user_id } userInfo.append(thisInfo) return JsonResponse.create(StatusCode.OK, {"users": userInfo})
def delete_submission(submission): """ Deletes all data associated with the specified submission NOTE: THERE IS NO WAY TO UNDO THIS """ if submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']: return JsonResponse.error(ValueError("Submissions that have been certified cannot be deleted"), StatusCode.CLIENT_ERROR) sess = GlobalDB.db().session # Check if the submission has any jobs that are currently running, if so, do not allow deletion jobs = sess.query(Job).filter(Job.submission_id == submission.submission_id, Job.job_status_id == JOB_STATUS_DICT['running']).all() if jobs: return JsonResponse.error(ValueError("Submissions with running jobs cannot be deleted"), StatusCode.CLIENT_ERROR) sess.query(SubmissionSubTierAffiliation).filter( SubmissionSubTierAffiliation.submission_id == submission.submission_id).delete( synchronize_session=False) sess.query(Submission).filter(Submission.submission_id == submission.submission_id).delete( synchronize_session=False) sess.expire_all() return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def getErrorMetrics(self) : """ Returns an Http response object containing error information for every validation job in specified submission """ responseDict = {} returnDict = {} try: safeDictionary = RequestDictionary(self.request) submission_id = safeDictionary.getValue("submission_id") # Check if user has permission to specified submission self.checkSubmissionPermission(self.jobManager.getSubmissionById(submission_id)) jobIds = self.jobManager.getJobsBySubmission(submission_id) for currentId in jobIds : if(self.jobManager.getJobType(currentId) == "csv_record_validation"): fileName = self.jobManager.getFileType(currentId) dataList = self.interfaces.errorDb.getErrorMetricsByJobId(currentId) returnDict[fileName] = dataList return JsonResponse.create(StatusCode.OK,returnDict) except ( ValueError , TypeError ) as e: return JsonResponse.error(e,StatusCode.CLIENT_ERROR) except ResponseException as e: return JsonResponse.error(e,e.status) except Exception as e: # Unexpected exception, this is a 500 server error return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
def list_submission_users(d2_submission): """ List user IDs and names that have submissions that the requesting user can see. Arguments: d2_submission: boolean indicating whether it is a DABS or FABS submission (True if FABS) Returns: A JsonResponse containing a list of users that have submissions that the requesting user can see """ sess = GlobalDB.db().session # subquery to create the EXISTS portion of the query exists_query = sess.query(Submission).filter( Submission.user_id == User.user_id, Submission.d2_submission.is_(d2_submission)) # if user is not an admin, we have to adjust the exists query to limit submissions if not g.user.website_admin: # split affiliations into frec and cgac cgac_affiliations = [aff for aff in g.user.affiliations if aff.cgac] frec_affiliations = [aff for aff in g.user.affiliations if aff.frec] # Don't list FABS permissions users if the user only has DABS permissions if not d2_submission: cgac_affiliations = [ aff for aff in cgac_affiliations if aff.permission_type_id in DABS_PERMISSION_ID_LIST ] frec_affiliations = [ aff for aff in frec_affiliations if aff.permission_type_id in DABS_PERMISSION_ID_LIST ] # Make a list of cgac and frec codes cgac_list = [aff.cgac.cgac_code for aff in cgac_affiliations] frec_list = [aff.frec.frec_code for aff in frec_affiliations] # Add filters where applicable affiliation_filters = [Submission.user_id == g.user.user_id] if cgac_list: affiliation_filters.append(Submission.cgac_code.in_(cgac_list)) if frec_list: affiliation_filters.append(Submission.frec_code.in_(frec_list)) exists_query = exists_query.filter(or_(*affiliation_filters)) # Add an exists onto the query, couldn't do this earlier because then the filters couldn't get added in the if exists_query = exists_query.exists() # Get all the relevant users user_results = sess.query(User.user_id, User.name).filter(exists_query).order_by( User.name).all() # Create an array containing relevant users in a readable format user_list = [] for user in user_results: user_list.append({'user_id': user[0], 'name': user[1]}) return JsonResponse.create(StatusCode.OK, {"users": user_list})
def resetPassword(self,system_email,session): """ Remove old password and email user a token to set a new password. Request should have key "email" arguments: system_email -- (string) email used to send messages session -- (Session) object from flask """ requestDict = RequestDictionary(self.request) if(not (requestDict.exists("email"))): # Don't have the keys we need in request exc = ResponseException("Reset password route requires key 'email'",StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) # Get user object try: user = self.interfaces.userDb.getUserByEmail(requestDict.getValue("email")) except Exception as e: exc = ResponseException("Unknown Error",StatusCode.CLIENT_ERROR,ValueError) return JsonResponse.error(exc,exc.status) LoginSession.logout(session) self.interfaces.userDb.session.commit() email = requestDict.getValue("email") # Send email with token emailToken = sesEmail.createToken(email,self.interfaces.userDb,"password_reset") link= "".join([ AccountHandler.FRONT_END,'#/forgotpassword/',emailToken]) emailTemplate = { '[URL]':link} newEmail = sesEmail(user.email, system_email,templateType="reset_password",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() # Return success message return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
def getErrorReportURLsForSubmission(self): """ Gets the Signed URLs for download based on the submissionId """ try : self.s3manager = s3UrlHandler() safeDictionary = RequestDictionary(self.request) submissionId = safeDictionary.getValue("submission_id") responseDict ={} for jobId in self.jobManager.getJobsBySubmission(submissionId): if(self.jobManager.getJobType(jobId) == "csv_record_validation"): if(not self.isLocal): responseDict["job_"+str(jobId)+"_error_url"] = self.s3manager.getSignedUrl("errors",self.jobManager.getReportPath(jobId),"GET") else: path = os.path.join(self.serverPath, self.jobManager.getReportPath(jobId)) responseDict["job_"+str(jobId)+"_error_url"] = path if(not self.isLocal): crossFileReport = self.s3manager.getSignedUrl("errors",self.jobManager.getCrossFileReportPath(submissionId),"GET") else: crossFileReport = os.path.join(self.serverPath, self.jobManager.getCrossFileReportPath(submissionId)) responseDict["cross_file_error_url"] = crossFileReport return JsonResponse.create(StatusCode.OK,responseDict) except ResponseException as e: return JsonResponse.error(e,StatusCode.CLIENT_ERROR) except Exception as e: # Unexpected exception, this is a 500 server error return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
def uploadFile(self): """saves a file and returns the saved path""" try: if(self.isLocal): uploadedFile = request.files['file'] if(uploadedFile): seconds = int((datetime.utcnow()-datetime(1970,1,1)).total_seconds()) filename = "".join([str(seconds),"_", secure_filename(uploadedFile.filename)]) path = os.path.join(self.serverPath, filename) uploadedFile.save(path) returnDict = {"path":path} return JsonResponse.create(StatusCode.OK,returnDict) else: exc = ResponseException("Failure to read file", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) else : exc = ResponseException("Route Only Valid For Local Installs", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) except ( ValueError , TypeError ) as e: return JsonResponse.error(e,StatusCode.CLIENT_ERROR) except ResponseException as e: return JsonResponse.error(e,e.status) except Exception as e: # Unexpected exception, this is a 500 server error return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
def email_users(self, system_email): """ Send email notification to list of users Args: system_email: the address of the system to send the email from Returns: A JsonReponse containing a message that the email sent successfully or the details of the missing parameters """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) required = ('users', 'submission_id', 'email_template') try: if any(field not in request_dict for field in required): raise ResponseException( "Email users route requires users, email_template, and submission_id", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc, exc.status) user_ids = request_dict['users'] submission_id = request_dict['submission_id'] # Check if submission id is valid _, agency_name = sess.query(Submission.submission_id, CGAC.agency_name).\ join(CGAC, Submission.cgac_code == CGAC.cgac_code).filter(Submission.submission_id == submission_id).one() if not agency_name: _, agency_name = sess.query(Submission.submission_id, FREC.agency_name).\ join(FREC, Submission.frec_code == FREC.frec_code).\ filter(Submission.submission_id == submission_id).one() template_type = request_dict['email_template'] # Check if email template type is valid get_email_template(template_type) users = [] link = "".join( [AccountHandler.FRONT_END, '#/reviewData/', str(submission_id)]) email_template = { '[REV_USER_NAME]': g.user.name, '[REV_AGENCY]': agency_name, '[REV_URL]': link } for user_id in user_ids: # Check if user id is valid, if so add User object to array users.append( sess.query(User).filter(User.user_id == user_id).one()) for user in users: new_email = SesEmail(user.email, system_email, template_type=template_type, parameters=email_template) new_email.send() return JsonResponse.create(StatusCode.OK, {"message": "Emails successfully sent"})
def createEmailConfirmation(self,system_email,session): """ Creates user record and email arguments: system_email -- (string) email used to send messages session -- (Session) object from flask """ requestFields = RequestDictionary(self.request) if(not requestFields.exists("email")): exc = ResponseException("Request body must include email", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) email = requestFields.getValue("email") if( not re.match("[^@]+@[^@]+\.[^@]+",email)) : return JsonResponse.error(ValueError("Invalid Email Format"),StatusCode.CLIENT_ERROR) try : user = self.interfaces.userDb.getUserByEmail(requestFields.getValue("email")) except ResponseException as e: self.interfaces.userDb.addUnconfirmedEmail(email) else: if(not (user.user_status_id == self.interfaces.userDb.getUserStatusId("awaiting_confirmation") or user.user_status_id == self.interfaces.userDb.getUserStatusId("email_confirmed"))): exc = ResponseException("User already registered", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) emailToken = sesEmail.createToken(email,self.interfaces.userDb,"validate_email") link= "".join([AccountHandler.FRONT_END,'#/registration/',emailToken]) emailTemplate = {'[USER]': email, '[URL]':link} newEmail = sesEmail(email, system_email,templateType="validate_email",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() return JsonResponse.create(StatusCode.OK,{"message":"Email Sent"})
def submit_files(): file_manager = FileHandler(request, is_local=is_local, server_path=server_path) sess = GlobalDB.db().session start_date = request.json.get('reporting_period_start_date') end_date = request.json.get('reporting_period_end_date') is_quarter = request.json.get('is_quarter_format', False) if not (start_date is None or end_date is None): formatted_start_date, formatted_end_date = FileHandler.check_submission_dates(start_date, end_date, is_quarter) submissions = sess.query(Submission).filter( Submission.cgac_code == request.json.get('cgac_code'), Submission.frec_code == request.json.get('frec_code'), Submission.reporting_start_date == formatted_start_date, Submission.reporting_end_date == formatted_end_date, Submission.is_quarter_format == request.json.get('is_quarter'), Submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']) if 'existing_submission_id' in request.json: submissions.filter(Submission.submission_id != request.json['existing_submission_id']) submissions = submissions.order_by(desc(Submission.created_at)) if submissions.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submissions[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return file_manager.submit(create_credentials)
def set_skip_guide(self): """ Set current user's skip guide parameter Returns: JsonResponse object containing results of setting the skip guide or details of the error that occurred. Possible errors include the request not containing a skip_guide parameter or it not being a boolean value """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) try: if 'skip_guide' not in request_dict: raise ResponseException("Must include skip_guide parameter", StatusCode.CLIENT_ERROR) skip_guide = str(request_dict['skip_guide']).lower() if skip_guide not in ("true", "false"): raise ResponseException("skip_guide must be true or false", StatusCode.CLIENT_ERROR) g.user.skip_guide = skip_guide == "true" except ResponseException as exc: return JsonResponse.error(exc, exc.status) sess.commit() return JsonResponse.create(StatusCode.OK, { "message": "skip_guide set successfully", "skip_guide": skip_guide })
def delete_submission(submission): """ Deletes all data associated with the specified submission NOTE: THERE IS NO WAY TO UNDO THIS """ if submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']: return JsonResponse.error(ValueError("Submissions that have been certified cannot be deleted"), StatusCode.CLIENT_ERROR) sess = GlobalDB.db().session # Check if the submission has any jobs that are currently running, if so, do not allow deletion jobs = sess.query(Job).filter(Job.submission_id == submission.submission_id, Job.job_status_id == JOB_STATUS_DICT['running']).all() if jobs: return JsonResponse.error(ValueError("Submissions with running jobs cannot be deleted"), StatusCode.CLIENT_ERROR) sess.query(SubmissionSubTierAffiliation).filter( SubmissionSubTierAffiliation.submission_id == submission.submission_id).delete( synchronize_session=False) sess.query(Submission).filter(Submission.submission_id == submission.submission_id).delete( synchronize_session=False) sess.expire_all() return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def submit_files(): file_manager = FileHandler(request, is_local=is_local, server_path=server_path) sess = GlobalDB.db().session start_date = request.json.get('reporting_period_start_date') end_date = request.json.get('reporting_period_end_date') is_quarter = request.json.get('is_quarter_format', False) if not (start_date is None or end_date is None): formatted_start_date, formatted_end_date = FileHandler.check_submission_dates(start_date, end_date, is_quarter) submissions = sess.query(Submission).filter( Submission.cgac_code == request.json.get('cgac_code'), Submission.frec_code == request.json.get('frec_code'), Submission.reporting_start_date == formatted_start_date, Submission.reporting_end_date == formatted_end_date, Submission.is_quarter_format == request.json.get('is_quarter'), Submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']) if 'existing_submission_id' in request.json: submissions.filter(Submission.submission_id != request.json['existing_submission_id']) submissions = submissions.order_by(desc(Submission.created_at)) if submissions.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submissions[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return file_manager.submit(create_credentials)
def finalize(self): """ Set upload job in job tracker database to finished, allowing dependent jobs to be started Flask request should include key "upload_id", which holds the job_id for the file_upload job Returns: A flask response object, if successful just contains key "success" with value True, otherwise value is False """ responseDict = {} try: inputDictionary = RequestDictionary(self.request) jobId = inputDictionary.getValue("upload_id") # Compare user ID with user who submitted job, if no match return 400 job = self.jobManager.getJobById(jobId) submission = self.jobManager.getSubmissionForJob(job) if(submission.user_id != LoginSession.getName(session)): # This user cannot finalize this job raise ResponseException("Cannot finalize a job created by a different user", StatusCode.CLIENT_ERROR) # Change job status to finished if(self.jobManager.checkUploadType(jobId)): self.jobManager.changeToFinished(jobId) responseDict["success"] = True return JsonResponse.create(StatusCode.OK,responseDict) else: raise ResponseException("Wrong job type for finalize route",StatusCode.CLIENT_ERROR) except ( ValueError , TypeError ) as e: return JsonResponse.error(e,StatusCode.CLIENT_ERROR) except ResponseException as e: return JsonResponse.error(e,e.status) except Exception as e: # Unexpected exception, this is a 500 server error return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
def get_submission_data(submission, file_type=''): """ Get data for the submission specified Args: submission: submission to retrieve metadata for file_type: the type of job to retrieve metadata for Returns: JsonResponse containing the error information or the object containing metadata for all relevant file types """ sess = GlobalDB.db().session file_type = file_type.lower() # Make sure the file type provided is valid if file_type and file_type not in FILE_TYPE_DICT and file_type != 'cross': return JsonResponse.error(ValueError(file_type + ' is not a valid file type'), StatusCode.CLIENT_ERROR) # Make sure the file type provided is valid for the submission type is_fabs = submission.d2_submission if file_type and (is_fabs and file_type != 'fabs') or (not is_fabs and file_type == 'fabs'): return JsonResponse.error(ValueError(file_type + ' is not a valid file type for this submission'), StatusCode.CLIENT_ERROR) job_query = sess.query(Job).filter(Job.submission_id == submission.submission_id) if not file_type: relevant_job_types = (JOB_TYPE_DICT['csv_record_validation'], JOB_TYPE_DICT['validation']) job_query = job_query.filter(Job.job_type_id.in_(relevant_job_types)) elif file_type == 'cross': job_query = job_query.filter(Job.job_type_id == JOB_TYPE_DICT['validation']) else: job_query = job_query.filter(Job.file_type_id == FILE_TYPE_DICT[file_type]) job_dict = {'jobs': [job_to_dict(job) for job in job_query]} return JsonResponse.create(StatusCode.OK, job_dict)
def listAgencies(self): agencies = self.validationManager.getAllAgencies() agency_list = [] for agency in agencies: agency_list.append({"agency_name": agency.agency_name, "cgac_code": agency.cgac_code}) return JsonResponse.create(StatusCode.OK, {"cgac_agency_list": agency_list})
def listSubmissionsByCurrentUser(self): """ List all submission IDs associated with the current user ID """ userId = LoginSession.getName(flaskSession) submissions = self.interfaces.jobDb.getSubmissionsByUserId(userId) submissionIdList = [] for submission in submissions: submissionIdList.append(submission.submission_id) return JsonResponse.create(StatusCode.OK,{"submission_id_list": submissionIdList})
def getRss(self): response = {} if self.isLocal: response["rss_url"] = os.path.join(self.serverPath, CONFIG_BROKER["rss_folder"],CONFIG_BROKER["rss_file"]) else: self.s3manager = s3UrlHandler() response["rss_url"] = self.s3manager.getSignedUrl(CONFIG_BROKER["rss_folder"],CONFIG_BROKER["rss_file"],"GET") return JsonResponse.create(200,response)
def getRss(self): """ Returns a signed URL to the RSS document. If local returns local path to RSS. """ response = {} if self.isLocal: response["rss_url"] = os.path.join(self.serverPath, CONFIG_BROKER["rss_folder"],CONFIG_BROKER["rss_file"]) else: self.s3manager = s3UrlHandler() response["rss_url"] = self.s3manager.getSignedUrl(CONFIG_BROKER["rss_folder"],CONFIG_BROKER["rss_file"],"GET") return JsonResponse.create(200,response)
def list_agencies(cgac_sub_tiers, frec_sub_tiers): """ Get all agencies the current user has DABS access to. Args: cgac_sub_tiers - List of all CGAC SubTierAgencies generated by the get_dabs_sub_tier_agencies decorator, required to list only sub_tier_agencies that user has DABS permissions for frec_sub_tiers - List of all FREC SubTierAgencies generated by the get_dabs_sub_tier_agencies decorator, required to list only sub_tier_agencies that user has DABS permissions for """ return JsonResponse.create(StatusCode.OK, get_accessible_agencies(cgac_sub_tiers, frec_sub_tiers))
def login(self,session): """ Logs a user in if their password matches arguments: session -- (Session) object from flask return the reponse object """ try: safeDictionary = RequestDictionary(self.request) username = safeDictionary.getValue('username') password = safeDictionary.getValue('password') try: user = self.interfaces.userDb.getUserByEmail(username) except Exception as e: raise ValueError("user name and or password invalid") if(not self.interfaces.userDb.checkStatus(user,"approved")): raise ValueError("user name and or password invalid") # Only check if user is active after they've logged in for the first time if user.last_login_date is not None and not self.isUserActive(user): raise ValueError("Your account has expired. Please contact an administrator.") try: if(self.interfaces.userDb.checkPassword(user,password,self.bcrypt)): # We have a valid login LoginSession.login(session,user.user_id) permissionList = [] for permission in self.interfaces.userDb.getPermssionList(): if(self.interfaces.userDb.hasPermission(user, permission.name)): permissionList.append(permission.permission_type_id) self.interfaces.userDb.updateLastLogin(user) return JsonResponse.create(StatusCode.OK,{"message":"Login successful","user_id": int(user.user_id),"name":user.name,"title":user.title ,"agency":user.agency, "permissions" : permissionList}) else : raise ValueError("user name and or password invalid") except Exception as e: LoginSession.logout(session) raise ValueError("user name and or password invalid") except (TypeError, KeyError, NotImplementedError) as e: # Return a 400 with appropriate message return JsonResponse.error(e,StatusCode.CLIENT_ERROR) except ValueError as e: # Return a 401 for login denied return JsonResponse.error(e,StatusCode.LOGIN_REQUIRED) except Exception as e: # Return 500 return JsonResponse.error(e,StatusCode.INTERNAL_ERROR) return self.response
def list_agencies(cgacs, frecs): """ List all CGAC and FREC Agencies Args: cgacs - List of all cgac codes that are valid for the user, generated by get_cgacs decorator, required to list only agencies that user can access frecs - List of all frec codes that are valid for the user, generated by get_frecs decorator, required to list only agencies that user can access """ agency_list = [{'agency_name': cgac.agency_name, 'cgac_code': cgac.cgac_code} for cgac in cgacs] shared_list = [{'agency_name': frec.agency_name, 'frec_code': frec.frec_code} for frec in frecs] return JsonResponse.create(StatusCode.OK, {'cgac_agency_list': agency_list, 'frec_agency_list': shared_list})
def find_existing_submissions_in_period(cgac_code, frec_code, reporting_fiscal_year, reporting_fiscal_period, submission_id=None): """ Find all the submissions in the given period for the given CGAC or FREC code Args: cgac_code: the CGAC code to check against or None if checking a FREC agency frec_code: the FREC code to check against or None if checking a CGAC agency reporting_fiscal_year: the year to check for reporting_fiscal_period: the period in the year to check for submission_id: the submission ID to check against (used when checking if this submission is being re-certified) Returns: A JsonResponse containing a success message to indicate there are no existing submissions in the given period or the error if there was one """ # We need either a cgac or a frec code for this function if not cgac_code and not frec_code: return JsonResponse.error(ValueError("CGAC or FR Entity Code required"), StatusCode.CLIENT_ERROR) sess = GlobalDB.db().session submission_query = sess.query(Submission).filter( (Submission.cgac_code == cgac_code) if cgac_code else (Submission.frec_code == frec_code), Submission.reporting_fiscal_year == reporting_fiscal_year, Submission.reporting_fiscal_period == reporting_fiscal_period, Submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']) # Filter out the submission we are potentially re-certifying if one is provided if submission_id: submission_query = submission_query.filter(Submission.submission_id != submission_id) submission_query = submission_query.order_by(desc(Submission.created_at)) if submission_query.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submission_query[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def find_existing_submissions_in_period(sess, cgac_code, frec_code, reporting_fiscal_year, reporting_fiscal_period, submission_id=None): submission_query = sess.query(Submission).filter( (Submission.cgac_code == cgac_code) if cgac_code else (Submission.frec_code == frec_code), Submission.reporting_fiscal_year == reporting_fiscal_year, Submission.reporting_fiscal_period == reporting_fiscal_period, Submission.publish_status_id != PUBLISH_STATUS_DICT['unpublished']) if submission_id: submission_query = submission_query.filter( Submission.submission_id != submission_id) submission_query = submission_query.order_by(desc(Submission.created_at)) if submission_query.count() > 0: data = { "message": "A submission with the same period already exists.", "submissionId": submission_query[0].submission_id } return JsonResponse.create(StatusCode.CLIENT_ERROR, data) return JsonResponse.create(StatusCode.OK, {"message": "Success"})
def check_detached_generation(job_id): """ Return information about detached file generation jobs Args: job_id: ID of the detached generation job Returns: Response object with keys job_id, status, file_type, url, message, start, and end. """ response_dict = generation_helper.check_file_generation(job_id) return JsonResponse.create(StatusCode.OK, response_dict)