def validate_account(caller, input): """Prompt the user to enter the received validation code.""" text = "" options = ( { "key": "b", "desc": "Go back to the email address menu.", "goto": "pre_email_address", }, { "key": "_default", "desc": "Enter the validation code.", "goto": "validate_account", }, ) account = caller.db._account if account.db.validation_code != input.strip(): text = dedent(""" |rSorry, the specified validation code {} doesn't match the one stored for this account. Is it the code you received by email? You can try to enter it again, Or enter |wb|n to choose a different email address. """.strip("\n")).format(input.strip()) else: account.db.valid = True account.attributes.remove("validation_code") account.record_email_address() caller.msg( "----- You will now create the first character of this account. -----" ) _login(caller, account) text = "" options = ({ "key": "_default", "desc": "Enter your new character's first name.", "goto": "create_first_name", }, ) return text, options
def confirm_password(caller, input): """Ask the user to confirm the account's password. The account's password has been saved in the session for the time being, as a hashed version. If the hashed version of the retyped password matches, then the player is created. If not, ask for another password. """ text = "" options = ( { "key": "b", "desc": "Go back to the password selection.", "goto": "create_password", }, { "key": "_default", "desc": "Enter your password.", "goto": "confirm_password", }, ) caller.msg(echo=True) password = input.strip() playername = caller.db._playername first_password = caller.db._password second_password = sha256(password).hexdigest() if first_password != second_password: text = dedent(""" |rThe password you have specified doesn't match the first one.|n Type |yb|n to choose a different password. Or type the confirmation password again. """.strip("\n")) else: # Creates the new player. from evennia.commands.default import unloggedin try: permissions = settings.PERMISSION_PLAYER_DEFAULT player = unloggedin._create_player(caller, playername, password, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg( dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Type |yb|n to go back to the login screen. Or enter another password. """.strip("\n"))) logger.log_trace() else: caller.db._player = player del caller.db._password _login(caller, player) text = "Your new account was successfully created!" text += "\n\n" + text_email_address(player) options = ({ "key": "_default", "desc": "Enter a valid e-mail address.", "goto": "email_address", }, ) return text, options
def password(caller, input): """Ask the user to enter the password to this player. This is assuming the user exists (see 'create_username' and 'create_password'). This node "loops" if needed: if the user specifies a wrong password, offers the user to try again or to go back by entering 'b'. If the password is correct, then login. """ caller.msg(echo=True) input = input.strip() text = "" options = ( { "key": "_default", "desc": "Enter your password.", "goto": "password", }, ) # Check the password player = caller.db._player # If the account is locked, the user has to wait (maximum # 3 seconds) before retrying if player.db._locked: text = "|gPlease wait, you cannot enter your password yet.|n" return text, options caller.msg(echo=True) bans = ServerConfig.objects.conf("server_bans") banned = bans and (any(tup[0] == player.name.lower() for tup in bans) \ or any(tup[2].match(caller.address) for tup in bans if tup[2])) if not player.check_password(input): caller.msg(echo=False) text = dedent(""" |rIncorrect password.|n Type |yb|n to go back to the login screen. Or wait 3 seconds before trying a new password. """.strip("\n")) # Loops on the same node player.scripts.add(WrongPassword) scripts = player.scripts.get("wrong_password") if scripts: script = scripts[0] script.db.session = caller else: print "Cannot retrieve the 'wrong_password' script." options = ( { "key": "b", "desc": "Go back to the login screen.", "goto": "start", }, { "key": "_default", "desc": "Enter your password again.", "goto": "password", }, ) elif banned: # This is a banned IP or name! string = dedent(""" |rYou have been banned and cannot continue from here.|n If you feel this ban is in error, please email an admin. """.strip("\n")) caller.msg(string) caller.sessionhandler.disconnect( caller, "Good bye! Disconnecting...") else: # The password is correct, we can log into the player. if not player.email: # Redirects to the node to set an e-mail address text = text_email_address(player) options = ( { "key": "_default", "desc": "Enter your e-mail address.", "goto": "email_address", }, ) elif not player.db.valid: # Redirects to the node for the validation code text = "Enter your received validation code." options = ( { "key": "_default", "desc": "Enter your validation code.", "goto": "validate_account", }, ) else: _login(caller, player) text = "" options = _options_choose_characters(player) return text, options
def confirm_password(caller, input): """Ask the user to confirm the account's password. The account's password has been saved in the session for the time being, as a hashed version. If the hashed version of the retyped password matches, then the player is created. If not, ask for another password. """ text = "" options = ( { "key": "b", "desc": "Go back to the password selection.", "goto": "create_password", }, { "key": "_default", "desc": "Enter your password.", "goto": "confirm_password", }, ) caller.msg(echo=True) password = input.strip() playername = caller.db._playername first_password = caller.db._password second_password = sha256(password).hexdigest() if first_password != second_password: text = dedent(""" |rThe password you have specified doesn't match the first one.|n Type |yb|n to choose a different password. Or type the confirmation password again. """.strip("\n")) else: # Creates the new player. from evennia.commands.default import unloggedin try: permissions = settings.PERMISSION_PLAYER_DEFAULT player = unloggedin._create_player(caller, playername, password, permissions) except Exception: # We are in the middle between logged in and -not, so we have # to handle tracebacks ourselves at this point. If we don't, we # won't see any errors at all. caller.msg(dedent(""" |rAn error occurred.|n Please e-mail an admin if the problem persists. Type |yb|n to go back to the login screen. Or enter another password. """.strip("\n"))) logger.log_trace() else: caller.db._player = player del caller.db._password _login(caller, player) text = "Your new account was successfully created!" text += "\n\n" + text_email_address(player) options = ( { "key": "_default", "desc": "Enter a valid e-mail address.", "goto": "email_address", }, ) return text, options
def email_address(caller, input): """Prompt the user to enter a valid email address.""" text = "" options = ({ "key": "_default", "desc": "Enter a valid email address.", "goto": "email_address", }, ) email_address = input.strip() account = caller.db._account # Search for accounts with an identical email address identical = list(Account.objects.filter(email__iexact=email_address)) if account in identical: identical.remove(account) # Try to validate the email address try: validate_email(email_address) except ValidationError: valid = False else: valid = True if not valid: # The email address doesn't seem to be valid text = dedent(""" |rSorry, the specified email address {} cannot be accepted as a valid one.|n Please enter another email address. """.strip("\n")).format(email_address) elif identical: # The email address is already used text = dedent(""" |rThe email address you have entered is already being used by another account. Please enter another email address. """.strip("\n")) else: account.email = email_address account.save() # Generates the 4-digit validation code numbers = "012345678" code = "" for i in range(4): code += choice(numbers) # Sends an email with the code subject = "[Avenew] Account validation" body = dedent(""" You have successfully created the account {} on Avenew. In order to validate it and begin to play, you need to enter the following four-digit code in your MUD client. If you have been disconnected, just login again, entering your account's name and password, the validation screen will appear. Four-digit code: {} """.strip("\n")).format(account.name, code) recipient = email_address account.db.valid = False account.db.validation_code = code try: assert not settings.TEST_SESSION send_email("NOREPLY", recipient, subject, body, store=False) except AssertionError: account.db.valid = True account.attributes.remove("validation_code") caller.msg( dedent(""" Avenew is in a test session mode, your account has been validated automatically. """.strip("\n")).format(email_address)) caller.msg( "----- You will now create the first character of this account. -----" ) _login(caller, account) text = "" options = ({ "key": "_default", "desc": "Enter your new character's first name.", "goto": "create_first_name", }, ) except (SMTPException, socket.error): # The email could not be sent account.db.valid = True account.attributes.remove("validation_code") caller.msg( dedent(""" Avenew couldn't send your email containing your validation code to {}. This is probably due to Avenew's failure to connect to the SMTP server. Your account has been validated automatically. """.strip("\n")).format(email_address)) caller.msg( "----- You will now create the first character of this account. -----" ) _login(caller, account) text = "" options = ({ "key": "_default", "desc": "Enter your new character's first name.", "goto": "create_first_name", }, ) else: text = dedent(""" An email has been sent to {}. It contains your validation code which you'll need in order to finish creating your account. If you haven't received the validation email after some minutes have passed, check your spam folder to see if it's inside of it. If not, you might want to select another email address, or contact an Avenew administrator. From here you can: Type |wb|n to choose a different email address. Enter your 4-digit validation code. """.strip("\n")).format(email_address) options = ( { "key": "b", "desc": "Go back to the email address selection.", "goto": "pre_email_address", }, { "key": "_default", "desc": "Enter your validation code.", "goto": "validate_account", }, ) return text, options
def password(caller, input): """Ask the user to enter the password to this account. This is assuming the user exists (see 'create_username' and 'create_password'). This node "loops" if needed: if the user specifies a wrong password, offers the user to try again or to go back by entering 'b'. If the password is correct, then login. """ input = input.strip() text = "" options = ({ "key": "_default", "desc": "Enter your password.", "goto": "password", }, ) # Check the password account = caller.db._account # If the account is locked, the user has to wait (maximum # 3 seconds) before retrying if account.db._locked: text = "|gPlease wait, you cannot enter your password yet.|n" return text, options bans = ServerConfig.objects.conf("server_bans") banned = bans and (any(tup[0] == account.name.lower() for tup in bans) \ or any(tup[2].match(caller.address) for tup in bans if tup[2])) if not account.check_password(input): text = dedent(""" |rIncorrect password.|n Type |wb|n to go back to the login screen. Or wait 3 seconds before trying a new password. """.strip("\n")) # Loops on the same node, lock for 3 seconds account.db._locked = True delay(3, _wrong_password, account) options = ( { "key": "b", "desc": "Go back to the login screen.", "goto": "pre_start", }, { "key": "_default", "desc": "Enter your password again.", "goto": "password", }, ) elif banned: # This is a banned IP or name string = dedent(""" |rYou have been banned and cannot continue from here.|n If you feel this ban is in error, please email an admin. """.strip("\n")) caller.msg(string) caller.sessionhandler.disconnect(caller, "Good bye! Disconnecting...") else: # The password is correct, we can log into the account. caller.msg(echo=True) if not account.email: # Redirects to the node to set an email address text = _text_email_address(account) options = ({ "key": "_default", "desc": "Enter your email address.", "goto": "email_address", }, ) elif not account.db.valid: # Redirects to the node for the validation code text = "Enter your 4-digit validation code." options = ({ "key": "_default", "desc": "Enter your validation code.", "goto": "validate_account", }, ) else: _login(caller, account) text = "" options = _options_choose_characters(account) if not account.db._playable_characters: options = ({ "key": "_default", "desc": "Enter your new character's first name.", "goto": "create_first_name", }, ) return text, options