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 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 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 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 logout(session): """ This function removes the session from the session table if currently logged in, and then returns a success message Args: session: the Session object Returns: a JsonResponse that the logout was successful """ # Call session handler LoginSession.logout(session) return JsonResponse.create(StatusCode.OK, {"message": "Logout successful"})
def logout(session): """ This function removes the session from the session table if currently logged in, and then returns a success message Args: session: the Session object Returns: a JsonResponse that the logout was successful """ # Call session handler LoginSession.logout(session) return JsonResponse.create(StatusCode.OK, {"message": "Logout successful"})
def login(self, session): """ Logs a user in if their password matches arguments: session -- (Session) object from flask return the response object """ try: sess = GlobalDB.db().session safe_dictionary = RequestDictionary(self.request) username = safe_dictionary.get_value('username') password = safe_dictionary.get_value('password') try: user = sess.query(User).filter( func.lower(User.email) == func.lower(username)).one() except Exception: raise ValueError("Invalid username and/or password") try: if check_correct_password(user, password, self.bcrypt): # We have a valid login return self.create_session_and_response(session, user) else: raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise e 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)
def logout(self,session): """ This function removes the session from the session table if currently logged in, and then returns a success message arguments: session -- (Session) object from flask return the reponse object """ # Call session handler LoginSession.logout(session) return JsonResponse.create(StatusCode.OK,{"message":"Logout successful"})
def logout(self,session): """ This function removes the session from the session table if currently logged in, and then returns a success message arguments: session -- (Session) object from flask return the reponse object """ # Call session handler LoginSession.logout(session) return JsonResponse.create(StatusCode.OK,{"message":"Logout successful"})
def login(self, session): """ Logs a user in if their password matches arguments: session -- (Session) object from flask return the response object """ try: sess = GlobalDB.db().session safe_dictionary = RequestDictionary(self.request) username = safe_dictionary.get_value('username') password = safe_dictionary.get_value('password') try: user = sess.query(User).filter(func.lower(User.email) == func.lower(username)).one() except Exception: raise ValueError("Invalid username and/or password") try: if check_correct_password(user, password, self.bcrypt): # We have a valid login return self.create_session_and_response(session, user) else: raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise e 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)
def login(self, session): """ Logs a user in if their password matches using local data Args: session: the Session object from flask Returns: A JsonResponse containing the user information or details on which error occurred, such as whether a type was wrong, something wasn't implemented, invalid keys were provided, login was denied, or a different, unexpected error occurred. """ try: sess = GlobalDB.db().session safe_dictionary = RequestDictionary(self.request) username = safe_dictionary.get_value('username') password = safe_dictionary.get_value('password') try: user = sess.query(User).filter( func.lower(User.email) == func.lower(username)).one() except Exception: raise ValueError("Invalid username and/or password") try: if check_correct_password(user, password, self.bcrypt): # We have a valid login return self.create_session_and_response(session, user) else: raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise e # Catch any specifically raised errors or any other errors that may have happened and return them cleanly 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)
def login(self, session): """ Logs a user in if their password matches using local data Args: session: the Session object from flask Returns: A JsonResponse containing the user information or details on which error occurred, such as whether a type was wrong, something wasn't implemented, invalid keys were provided, login was denied, or a different, unexpected error occurred. """ try: sess = GlobalDB.db().session safe_dictionary = RequestDictionary(self.request) username = safe_dictionary.get_value('username') password = safe_dictionary.get_value('password') try: user = sess.query(User).filter(func.lower(User.email) == func.lower(username)).one() except Exception: raise ValueError("Invalid username and/or password") try: if check_correct_password(user, password, self.bcrypt): # We have a valid login return self.create_session_and_response(session, user) else: raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise e # Catch any specifically raised errors or any other errors that may have happened and return them cleanly 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)
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 register(self,system_email,session): """ Save user's information into user database. Associated request body should have keys 'email', 'name', 'cgac_code', and 'title' arguments: system_email -- (string) email used to send messages session -- (Session) object from flask Returns message that registration is successful or error message that fields are not valid """ def ThreadedFunction (username="", title="", cgac_code="", user_email="" , link="") : """ This inner function sends emails in a new thread as there could be lots of admins username -- (string) the name of the user title -- (string) the title of the user cgac_code -- (string) the agency of the user user_email -- (string) the email of the user link -- (string) the broker email link """ agency_name = sess.query(CGAC.agency_name).\ filter(CGAC.cgac_code == cgac_code).\ one_or_none() agency_name = "Unknown" if agency_name is None else agency_name for user in sess.query(User).filter_by(permission_type_id=PERMISSION_TYPE_DICT['website_admin']): email_template = {'[REG_NAME]': username, '[REG_TITLE]':title, '[REG_AGENCY_NAME]':agency_name, '[REG_CGAC_CODE]': cgac_code,'[REG_EMAIL]' : user_email,'[URL]':link} new_email = sesEmail(user.email, system_email,templateType="account_creation",parameters=email_template) new_email.send() sess = GlobalDB.db().session request_fields = RequestDictionary.derive(self.request) try: required = ('email', 'name', 'cgac_code', 'title', 'password') if any(field not in request_fields for field in required): # Missing a required field, return 400 raise ResponseException( "Request body must include email, name, cgac_code, " "title, and password", StatusCode.CLIENT_ERROR ) if not self.checkPassword(request_fields["password"]): raise ResponseException( "Invalid Password", StatusCode.CLIENT_ERROR) # Find user that matches specified email user = sess.query(User).filter( func.lower(User.email) == func.lower(request_fields['email']) ).one_or_none() if user is None: raise ResponseException( "No users with that email", StatusCode.CLIENT_ERROR) # Check that user's status is before submission of registration bad_statuses = (USER_STATUS_DICT["awaiting_confirmation"], USER_STATUS_DICT["email_confirmed"]) if user.user_status_id not in bad_statuses: # Do not allow duplicate registrations raise ResponseException( "User already registered", StatusCode.CLIENT_ERROR) # Add user info to database user.name = request_fields['name'] user.cgac_code = request_fields['cgac_code'] user.title = request_fields['title'] sess.commit() set_user_password(user, request_fields['password'], self.bcrypt) except ResponseException as exc: return JsonResponse.error(exc, exc.status) user_link= "".join([AccountHandler.FRONT_END, '#/login?redirect=/admin']) # Send email to approver list email_thread = Thread(target=ThreadedFunction, kwargs=dict(username=user.name,title=user.title,cgac_code=user.cgac_code,user_email=user.email,link=user_link)) email_thread.start() #email user email_template = {'[EMAIL]' : system_email} new_email = sesEmail(user.email, system_email,templateType="account_creation_user",parameters=email_template) new_email.send() # Logout and delete token LoginSession.logout(session) oldToken = sess.query(EmailToken).filter(EmailToken.token == session["token"]).one() sess.delete(oldToken) # Mark user as awaiting approval user.user_status_id = USER_STATUS_DICT["awaiting_approval"] sess.commit() return JsonResponse.create(StatusCode.OK,{"message":"Registration successful"})
def register(self,system_email,session): """ Save user's information into user database. Associated request body should have keys 'email', 'name', 'agency', and 'title' arguments: system_email -- (string) email used to send messages session -- (Session) object from flask Returns message that registration is successful or error message that fields are not valid """ def ThreadedFunction (from_email="",username="",title="",agency="",userEmail="" ,link="") : """ This inner function sends emails in a new thread as there could be lots of admins from_email -- (string) the from email address username -- (string) the name of the user title -- (string) the title of the user agency -- (string) the agency of the user userEmail -- (string) the email of the user link -- (string) the broker email link """ threadedDatabase = UserHandler() try: for user in threadedDatabase.getUsersByType("website_admin") : emailTemplate = {'[REG_NAME]': username, '[REG_TITLE]':title, '[REG_AGENCY]':agency,'[REG_EMAIL]' : userEmail,'[URL]':link} newEmail = sesEmail(user.email, system_email,templateType="account_creation",parameters=emailTemplate,database=threadedDatabase) newEmail.send() finally: InterfaceHolder.closeOne(threadedDatabase) requestFields = RequestDictionary(self.request) if(not (requestFields.exists("email") and requestFields.exists("name") and requestFields.exists("agency") and requestFields.exists("title") and requestFields.exists("password"))): # Missing a required field, return 400 exc = ResponseException("Request body must include email, name, agency, title, and password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) if(not self.checkPassword(requestFields.getValue("password"))): exc = ResponseException("Invalid Password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) # Find user that matches specified email user = self.interfaces.userDb.getUserByEmail(requestFields.getValue("email")) # Check that user's status is before submission of registration if not (self.interfaces.userDb.checkStatus(user,"awaiting_confirmation") or self.interfaces.userDb.checkStatus(user,"email_confirmed")): # Do not allow duplicate registrations exc = ResponseException("User already registered",StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) # Add user info to database self.interfaces.userDb.addUserInfo(user,requestFields.getValue("name"),requestFields.getValue("agency"),requestFields.getValue("title")) self.interfaces.userDb.setPassword(user,requestFields.getValue("password"),self.bcrypt) userLink= "".join([AccountHandler.FRONT_END, '#/login?redirect=/admin']) # Send email to approver list emailThread = Thread(target=ThreadedFunction, kwargs=dict(from_email=system_email,username=user.name,title=user.title,agency=user.agency,userEmail=user.email,link=userLink)) emailThread.start() #email user link= AccountHandler.FRONT_END emailTemplate = {'[EMAIL]' : system_email} newEmail = sesEmail(user.email, system_email,templateType="account_creation_user",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() LoginSession.logout(session) # Mark user as awaiting approval self.interfaces.userDb.changeStatus(user,"awaiting_approval") return JsonResponse.create(StatusCode.OK,{"message":"Registration successful"})
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("Invalid username and/or password") if(not self.interfaces.userDb.checkStatus(user,"approved")): raise ValueError("Invalid username and/or password") # Only check if user is active after they've logged in for the first time if user.last_login_date is not None and self.isAccountExpired(user): raise ValueError("Your account has expired. Please contact an administrator.") # for whatever reason, your account is not active, therefore it's locked if not self.isUserActive(user): raise ValueError("Your account has been locked. Please contact an administrator.") try: if(self.interfaces.userDb.checkPassword(user,password,self.bcrypt)): # We have a valid login # Reset incorrect password attempt count to 0 self.resetPasswordCount(user) LoginSession.login(session,user.user_id) permissionList = [] for permission in self.interfaces.userDb.getPermissionList(): if(self.interfaces.userDb.hasPermission(user, permission.name)): permissionList.append(permission.permission_type_id) self.interfaces.userDb.updateLastLogin(user) agency_name = self.interfaces.validationDb.getAgencyName(user.cgac_code) return JsonResponse.create(StatusCode.OK,{"message":"Login successful","user_id": int(user.user_id), "name":user.name,"title":user.title,"agency_name":agency_name, "cgac_code":user.cgac_code, "permissions" : permissionList}) else : # increase incorrect password attempt count by 1 # if this is the 3rd incorrect attempt, lock account self.incrementPasswordCount(user) if user.incorrect_password_attempts == 3: raise ValueError("Your account has been locked due to too many failed login attempts. Please contact an administrator.") raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise ValueError("Invalid username and/or password") 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 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 login(self,session): """ Logs a user in if their password matches arguments: session -- (Session) object from flask return the response object """ try: sess = GlobalDB.db().session safe_dictionary = RequestDictionary(self.request) username = safe_dictionary.getValue('username') password = safe_dictionary.getValue('password') try: user = sess.query(User).filter(func.lower(User.email) == func.lower(username)).one() except Exception: raise ValueError("Invalid username and/or password") if user.user_status_id != USER_STATUS_DICT["approved"]: raise ValueError("Invalid username and/or password") # Only check if user is active after they've logged in for the first time if user.last_login_date is not None and self.isAccountExpired(user): raise ValueError("Your account has expired. Please contact an administrator.") # for whatever reason, your account is not active, therefore it's locked if not user.is_active: raise ValueError("Your account has been locked. Please contact an administrator.") try: if check_correct_password(user,password,self.bcrypt): # We have a valid login # Reset incorrect password attempt count to 0 self.reset_password_count(user) return self.create_session_and_response(session, user) else : # increase incorrect password attempt count by 1 # if this is the 3rd incorrect attempt, lock account self.incrementPasswordCount(user) if user.incorrect_password_attempts == 3: raise ValueError("Your account has been locked due to too many failed login attempts. Please contact an administrator.") raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise e 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)
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("Invalid username and/or password") if (not self.interfaces.userDb.checkStatus(user, "approved")): raise ValueError("Invalid username and/or password") # Only check if user is active after they've logged in for the first time if user.last_login_date is not None and self.isAccountExpired( user): raise ValueError( "Your account has expired. Please contact an administrator." ) # for whatever reason, your account is not active, therefore it's locked if not self.isUserActive(user): raise ValueError( "Your account has been locked. Please contact an administrator." ) try: if (self.interfaces.userDb.checkPassword( user, password, self.bcrypt)): # We have a valid login # Reset incorrect password attempt count to 0 self.resetPasswordCount(user) LoginSession.login(session, user.user_id) permissionList = [] for permission in self.interfaces.userDb.getPermissionList( ): if (self.interfaces.userDb.hasPermission( user, permission.name)): permissionList.append( permission.permission_type_id) self.interfaces.userDb.updateLastLogin(user) agency_name = self.interfaces.validationDb.getAgencyName( user.cgac_code) return JsonResponse.create( StatusCode.OK, { "message": "Login successful", "user_id": int(user.user_id), "name": user.name, "title": user.title, "agency_name": agency_name, "cgac_code": user.cgac_code, "permissions": permissionList }) else: # increase incorrect password attempt count by 1 # if this is the 3rd incorrect attempt, lock account self.incrementPasswordCount(user) if user.incorrect_password_attempts == 3: raise ValueError( "Your account has been locked due to too many failed login attempts. Please contact an administrator." ) raise ValueError("Invalid username and/or password") except ValueError as ve: LoginSession.logout(session) raise ve except Exception as e: LoginSession.logout(session) raise ValueError("Invalid username and/or password") 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 register(self, system_email, session): """ Save user's information into user database. Associated request body should have keys 'email', 'name', 'cgac_code', and 'title' arguments: system_email -- (string) email used to send messages session -- (Session) object from flask Returns message that registration is successful or error message that fields are not valid """ def ThreadedFunction(from_email="", username="", title="", cgac_code="", userEmail="", link=""): """ This inner function sends emails in a new thread as there could be lots of admins from_email -- (string) the from email address username -- (string) the name of the user title -- (string) the title of the user agency -- (string) the agency of the user userEmail -- (string) the email of the user link -- (string) the broker email link """ threadedDatabase = UserHandler() try: agency_name = self.interfaces.validationDb.getAgencyName( cgac_code) agency_name = "Unknown" if agency_name is None else agency_name for user in threadedDatabase.getUsersByType("website_admin"): emailTemplate = { '[REG_NAME]': username, '[REG_TITLE]': title, '[REG_AGENCY_NAME]': agency_name, '[REG_CGAC_CODE]': cgac_code, '[REG_EMAIL]': userEmail, '[URL]': link } newEmail = sesEmail(user.email, system_email, templateType="account_creation", parameters=emailTemplate, database=threadedDatabase) newEmail.send() for user in threadedDatabase.getUsersByType("agency_admin"): if user.cgac_code == cgac_code: emailTemplate = { '[REG_NAME]': username, '[REG_TITLE]': title, '[REG_AGENCY_NAME]': agency_name, '[REG_CGAC_CODE]': cgac_code, '[REG_EMAIL]': userEmail, '[URL]': link } newEmail = sesEmail(user.email, system_email, templateType="account_creation", parameters=emailTemplate, database=threadedDatabase) newEmail.send() finally: threadedDatabase.close() requestFields = RequestDictionary(self.request) if (not (requestFields.exists("email") and requestFields.exists("name") and requestFields.exists("cgac_code") and requestFields.exists("title") and requestFields.exists("password"))): # Missing a required field, return 400 exc = ResponseException( "Request body must include email, name, cgac_code, title, and password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) if (not self.checkPassword(requestFields.getValue("password"))): exc = ResponseException("Invalid Password", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Find user that matches specified email user = self.interfaces.userDb.getUserByEmail( requestFields.getValue("email")) # Check that user's status is before submission of registration if not (self.interfaces.userDb.checkStatus(user, "awaiting_confirmation") or self.interfaces.userDb.checkStatus(user, "email_confirmed")): # Do not allow duplicate registrations exc = ResponseException("User already registered", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Add user info to database self.interfaces.userDb.addUserInfo(user, requestFields.getValue("name"), requestFields.getValue("cgac_code"), requestFields.getValue("title")) self.interfaces.userDb.setPassword(user, requestFields.getValue("password"), self.bcrypt) userLink = "".join( [AccountHandler.FRONT_END, '#/login?redirect=/admin']) # Send email to approver list emailThread = Thread(target=ThreadedFunction, kwargs=dict(from_email=system_email, username=user.name, title=user.title, cgac_code=user.cgac_code, userEmail=user.email, link=userLink)) emailThread.start() #email user link = AccountHandler.FRONT_END emailTemplate = {'[EMAIL]': system_email} newEmail = sesEmail(user.email, system_email, templateType="account_creation_user", parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send() # Logout and delete token LoginSession.logout(session) self.interfaces.userDb.deleteToken(session["token"]) # Mark user as awaiting approval self.interfaces.userDb.changeStatus(user, "awaiting_approval") return JsonResponse.create(StatusCode.OK, {"message": "Registration successful"})