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: InterfaceHolder.closeOne(threadedDatabase)
def changeStatus(self, system_email): """ Changes status for specified user. Associated request body should have keys 'uid' and 'new_status' arguments: system_email -- (string) the emaily to send emails from return the reponse object with a success message """ requestDict = RequestDictionary(self.request) if (not (requestDict.exists("uid") and requestDict.exists("new_status"))): # Missing a required field, return 400 exc = ResponseException( "Request body must include uid and new_status", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Find user that matches specified uid user = self.interfaces.userDb.getUserByUID( int(requestDict.getValue("uid"))) if (user.email == None): return JsonResponse.error( ResponseException("User does not have a defined email", StatusCode.INTERNAL_ERROR), StatusCode.INTERNAL_ERROR) #check if the user is waiting if (self.interfaces.userDb.checkStatus(user, "awaiting_approval")): if (requestDict.getValue("new_status") == "approved"): # Grant agency_user permission to newly approved users self.interfaces.userDb.grantPermission(user, "agency_user") link = AccountHandler.FRONT_END emailTemplate = {'[URL]': link, '[EMAIL]': system_email} newEmail = sesEmail(user.email, system_email, templateType="account_approved", parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send() elif (requestDict.getValue("new_status") == "denied"): emailTemplate = {} newEmail = sesEmail(user.email, system_email, templateType="account_rejected", parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send() # Change user's status self.interfaces.userDb.changeStatus(user, requestDict.getValue("new_status")) return JsonResponse.create(StatusCode.OK, {"message": "Status change successful"})
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()
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)
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 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 sendResetPasswordEmail(self, user, system_email, email=None, unlock_user=False): if email is None: email = user.email # User must be approved and active to reset password if user.user_status_id != self.interfaces.userDb.getUserStatusId( "approved"): raise ResponseException( "User must be approved before resetting password", StatusCode.CLIENT_ERROR) elif not unlock_user and not user.is_active: raise ResponseException("User is locked, cannot reset password", StatusCode.CLIENT_ERROR) # If unlocking a user, wipe out current password if unlock_user: UserHandler().clearPassword(user) self.interfaces.userDb.session.commit() # Send email with token emailToken = sesEmail.createToken(email, "password_reset") link = "".join( [AccountHandler.FRONT_END, '#/forgotpassword/', emailToken]) emailTemplate = {'[URL]': link} templateType = "unlock_account" if unlock_user else "reset_password" newEmail = sesEmail(user.email, system_email, templateType=templateType, parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send()
def changeStatus(self,system_email): """ Changes status for specified user. Associated request body should have keys 'uid' and 'new_status' arguments: system_email -- (string) the emaily to send emails from return the reponse object with a success message """ requestDict = RequestDictionary(self.request) if(not (requestDict.exists("uid") and requestDict.exists("new_status"))): # Missing a required field, return 400 exc = ResponseException("Request body must include uid and new_status", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc,exc.status) # Find user that matches specified uid user = self.interfaces.userDb.getUserByUID(int(requestDict.getValue("uid"))) if(user.email == None): return JsonResponse.error(ResponseException("User does not have a defined email",StatusCode.INTERNAL_ERROR),StatusCode.INTERNAL_ERROR) #check if the user is waiting if(self.interfaces.userDb.checkStatus(user,"awaiting_approval")): if(requestDict.getValue("new_status") == "approved"): # Grant agency_user permission to newly approved users self.interfaces.userDb.grantPermission(user,"agency_user") link= AccountHandler.FRONT_END emailTemplate = { '[URL]':link,'[EMAIL]':system_email} newEmail = sesEmail(user.email, system_email,templateType="account_approved",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() elif (requestDict.getValue("new_status") == "denied"): emailTemplate = {} newEmail = sesEmail(user.email, system_email,templateType="account_rejected",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() # Change user's status self.interfaces.userDb.changeStatus(user,requestDict.getValue("new_status")) return JsonResponse.create(StatusCode.OK,{"message":"Status change successful"})
def create_email_confirmation(self,system_email): """ Creates user record and email arguments: system_email -- (string) email used to send messages """ sess = GlobalDB.db().session request_fields = RequestDictionary.derive(self.request) try: if 'email' not in request_fields: raise ResponseException( "Request body must include email", StatusCode.CLIENT_ERROR) email = request_fields['email'] if not re.match("[^@]+@[^@]+\.[^@]+",email): raise ValueError("Invalid Email Format") except (ResponseException, ValueError) as exc: return JsonResponse.error(exc, StatusCode.CLIENT_ERROR) try : user = sess.query(User).filter( func.lower(User.email) == func.lower(request_fields['email']) ).one() except NoResultFound: # Create user with specified email if none is found user = User(email=email) user.user_status_id = USER_STATUS_DICT["awaiting_confirmation"] user.permissions = 0 sess.add(user) sess.commit() else: try: good_statuses = (USER_STATUS_DICT["awaiting_confirmation"], USER_STATUS_DICT["email_confirmed"]) if user.user_status_id not in good_statuses: raise ResponseException( "User already registered", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc, exc.status) email_token = sesEmail.createToken(email, "validate_email") link= "".join([AccountHandler.FRONT_END,'#/registration/',email_token]) email_template = {'[USER]': email, '[URL]':link} new_email = sesEmail(email, system_email,templateType="validate_email",parameters=email_template) new_email.send() return JsonResponse.create(StatusCode.OK,{"message":"Email Sent"})
def emailUsers(self, system_email, session): """ Send email notification to list of users """ requestDict = RequestDictionary(self.request) if not (requestDict.exists("users") and requestDict.exists("submission_id") and requestDict.exists("email_template")): exc = ResponseException( "Email users route requires users, email_template, and submission_id", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) uid = session["name"] current_user = self.interfaces.userDb.getUserByUID(uid) user_ids = requestDict.getValue("users") submission_id = requestDict.getValue("submission_id") # Check if submission id is valid self.jobManager.getSubmissionById(submission_id) template_type = requestDict.getValue("email_template") # Check if email template type is valid self.userManager.getEmailTemplate(template_type) users = [] link = "".join( [AccountHandler.FRONT_END, '#/reviewData/', str(submission_id)]) emailTemplate = { '[REV_USER_NAME]': current_user.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(self.userManager.getUserByUID(user_id)) for user in users: newEmail = sesEmail(user.email, system_email, templateType=template_type, parameters=emailTemplate, database=UserHandler()) newEmail.send() return JsonResponse.create(StatusCode.OK, {"message": "Emails successfully sent"})
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 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 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)
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()
def email_users(self, system_email, session): """ Send email notification to list of users """ 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) current_user = sess.query(User).filter(User.user_id == session["name"]).one() user_ids = request_dict['users'] submission_id = request_dict['submission_id'] # Check if submission id is valid sess.query(Submission).filter_by(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]': current_user.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, templateType=template_type, parameters=email_template) new_email.send() return JsonResponse.create(StatusCode.OK, {"message": "Emails successfully sent"})
def sendResetPasswordEmail(self, user, system_email, email=None, unlock_user=False): if email is None: email = user.email # User must be approved and active to reset password if user.user_status_id != self.interfaces.userDb.getUserStatusId("approved"): raise ResponseException("User must be approved before resetting password", StatusCode.CLIENT_ERROR) elif not unlock_user and not user.is_active: raise ResponseException("User is locked, cannot reset password", StatusCode.CLIENT_ERROR) # If unlocking a user, wipe out current password if unlock_user: UserHandler().clearPassword(user) self.interfaces.userDb.session.commit() # Send email with token emailToken = sesEmail.createToken(email, self.interfaces.userDb, "password_reset") link = "".join([AccountHandler.FRONT_END, '#/forgotpassword/', emailToken]) emailTemplate = {'[URL]': link} templateType = "unlock_account" if unlock_user else "reset_password" newEmail = sesEmail(user.email, system_email, templateType=templateType, parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send()
def send_reset_password_email(self, user, system_email, email=None, unlock_user=False): sess = GlobalDB.db().session if email is None: email = user.email # User must be approved and active to reset password if user.user_status_id != USER_STATUS_DICT["approved"]: raise ResponseException("User must be approved before resetting password", StatusCode.CLIENT_ERROR) elif not unlock_user and not user.is_active: raise ResponseException("User is locked, cannot reset password", StatusCode.CLIENT_ERROR) # If unlocking a user, wipe out current password if unlock_user: user.salt = None user.password_hash = None sess.commit() # Send email with token email_token = sesEmail.createToken(email, "password_reset") link = "".join([AccountHandler.FRONT_END, '#/forgotpassword/', email_token]) email_template = {'[URL]': link} template_type = "unlock_account" if unlock_user else "reset_password" new_email = sesEmail(user.email, system_email, templateType=template_type, parameters=email_template) new_email.send()
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"})
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 update_user(self, system_email): """ Update editable fields for specified user. Editable fields for a user: * is_active * user_status_id Args: system_email: address the email is sent from Request body should contain the following keys: * uid (integer) * status (string) * is_active (boolean) Returns: JSON response object with either an exception or success message """ sess = GlobalDB.db().session request_dict = RequestDictionary.derive(self.request) try: editable_fields = ('status', 'permissions', 'is_active') has_editable = any(key in request_dict for key in editable_fields) if 'uid' not in request_dict or not has_editable: # missing required fields, return 400 raise ResponseException( "Request body must include uid and at least one of the " "following: status, permissions, is_active", StatusCode.CLIENT_ERROR ) # Find user that matches specified uid user = sess.query(User).filter_by( user_id=int(request_dict['uid'])).one_or_none() if user is None: raise ResponseException( "No users with that uid", StatusCode.CLIENT_ERROR) except ResponseException as exc: return JsonResponse.error(exc, exc.status) if 'status' in request_dict: #check if the user is waiting if user.user_status_id == USER_STATUS_DICT["awaiting_approval"]: if request_dict['status'] == 'approved': # Grant agency_user permission to newly approved users user.permission_type_id = PERMISSION_TYPE_DICT['reader'] sess.merge(user) sess.commit() link = AccountHandler.FRONT_END email_template = {'[URL]':link,'[EMAIL]':system_email} new_email = sesEmail(user.email, system_email,templateType="account_approved",parameters=email_template) new_email.send() elif request_dict['status'] == 'denied': email_template = {} new_email = sesEmail(user.email, system_email,templateType="account_rejected",parameters=email_template) new_email.send() # Change user's status try: user.user_status_id = USER_STATUS_DICT[request_dict['status']] except ValueError as e: # In this case having a bad status name is a client error raise ResponseException(str(e), StatusCode.CLIENT_ERROR, ValueError) sess.commit() # Activate/deactivate user if 'is_active' in request_dict: is_active = bool(request_dict['is_active']) user.is_active = is_active sess.commit() return JsonResponse.create(StatusCode.OK, {"message": "User successfully updated"})
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 updateUser(self, system_email): """ Update editable fields for specified user. Editable fields for a user: * is_active * user_status_id * permissions Args: None: Request body should contain the following keys: * uid (integer) * status (string) * permissions (comma separated string) * is_active (boolean) Returns: JSON response object with either an exception or success message """ requestDict = RequestDictionary(self.request) # throw an exception if nothing is provided in the request if not requestDict.exists("uid") or not (requestDict.exists("status") or requestDict.exists("permissions") or requestDict.exists("is_active")): # missing required fields, return 400 exc = ResponseException("Request body must include uid and at least one of the following: status, permissions, is_active", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Find user that matches specified uid user = self.interfaces.userDb.getUserByUID(int(requestDict.getValue("uid"))) if requestDict.exists("status"): #check if the user is waiting if(self.interfaces.userDb.checkStatus(user,"awaiting_approval")): if(requestDict.getValue("status") == "approved"): # Grant agency_user permission to newly approved users self.interfaces.userDb.grantPermission(user,"agency_user") link= AccountHandler.FRONT_END emailTemplate = { '[URL]':link,'[EMAIL]':system_email} newEmail = sesEmail(user.email, system_email,templateType="account_approved",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() elif (requestDict.getValue("status") == "denied"): emailTemplate = {} newEmail = sesEmail(user.email, system_email,templateType="account_rejected",parameters=emailTemplate,database=self.interfaces.userDb) newEmail.send() # Change user's status self.interfaces.userDb.changeStatus(user,requestDict.getValue("status")) if requestDict.exists("permissions"): permissions_list = requestDict.getValue("permissions").split(',') # Remove all existing permissions for user user_permissions = self.interfaces.userDb.getUserPermissions(user) for permission in user_permissions: self.interfaces.userDb.removePermission(user, permission) # Grant specified permissions for permission in permissions_list: self.interfaces.userDb.grantPermission(user, permission) # Activate/deactivate user if requestDict.exists("is_active"): is_active = bool(requestDict.getValue("is_active")) if not self.isUserActive(user) and is_active: # Reset password count to 0 self.resetPasswordCount(user) # Reset last login date so the account isn't expired self.interfaces.userDb.updateLastLogin(user, unlock_user=True) self.sendResetPasswordEmail(user, system_email, unlock_user=True) self.interfaces.userDb.setUserActive(user, is_active) return JsonResponse.create(StatusCode.OK, {"message": "User successfully updated"})
def updateUser(self, system_email): """ Update editable fields for specified user. Editable fields for a user: * is_active * user_status_id * permissions Args: None: Request body should contain the following keys: * uid (integer) * status (string) * permissions (comma separated string) * is_active (boolean) Returns: JSON response object with either an exception or success message """ requestDict = RequestDictionary(self.request) # throw an exception if nothing is provided in the request if not requestDict.exists("uid") or not ( requestDict.exists("status") or requestDict.exists("permissions") or requestDict.exists("is_active")): # missing required fields, return 400 exc = ResponseException( "Request body must include uid and at least one of the following: status, permissions, is_active", StatusCode.CLIENT_ERROR) return JsonResponse.error(exc, exc.status) # Find user that matches specified uid user = self.interfaces.userDb.getUserByUID( int(requestDict.getValue("uid"))) if requestDict.exists("status"): #check if the user is waiting if (self.interfaces.userDb.checkStatus(user, "awaiting_approval")): if (requestDict.getValue("status") == "approved"): # Grant agency_user permission to newly approved users self.interfaces.userDb.grantPermission(user, "agency_user") link = AccountHandler.FRONT_END emailTemplate = {'[URL]': link, '[EMAIL]': system_email} newEmail = sesEmail(user.email, system_email, templateType="account_approved", parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send() elif (requestDict.getValue("status") == "denied"): emailTemplate = {} newEmail = sesEmail(user.email, system_email, templateType="account_rejected", parameters=emailTemplate, database=self.interfaces.userDb) newEmail.send() # Change user's status self.interfaces.userDb.changeStatus(user, requestDict.getValue("status")) if requestDict.exists("permissions"): permissions_list = requestDict.getValue("permissions").split(',') # Remove all existing permissions for user user_permissions = self.interfaces.userDb.getUserPermissions(user) for permission in user_permissions: self.interfaces.userDb.removePermission(user, permission) # Grant specified permissions for permission in permissions_list: self.interfaces.userDb.grantPermission(user, permission) # Activate/deactivate user if requestDict.exists("is_active"): is_active = bool(requestDict.getValue("is_active")) if not self.isUserActive(user) and is_active: # Reset password count to 0 self.resetPasswordCount(user) # Reset last login date so the account isn't expired self.interfaces.userDb.updateLastLogin(user, unlock_user=True) self.sendResetPasswordEmail(user, system_email, unlock_user=True) self.interfaces.userDb.setUserActive(user, is_active) return JsonResponse.create(StatusCode.OK, {"message": "User successfully updated"})