def test_admin_can_ban_email_domain(client, user_info, test_config): register_user(client, user_info) promote_user_to_admin(client, user_info) rv = client.get(url_for("admin.domains", domain_type="email")) rv = client.post( url_for("do.ban_domain", domain_type="email"), data=dict(csrf_token=csrf_token(rv.data), domain="spam4u.com"), follow_redirects=True, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" log_out_current_user(client) rv = client.get(url_for("auth.register")) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username="******", password="******", confirm="Safe123#$@lolnot", email_required="*****@*****.**", invitecode="", accept_tos=True, captcha="xyzzy", ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert len(outbox) == 0 assert b"do not accept emails" in rv.data assert b"Register" in rv.data assert b"Log out" not in rv.data
def test_reset_password(client, user_info): """A user can reset their password using a link sent to their email.""" new_password = '******' assert new_password != user_info['password'] register_user(client, user_info) log_out_current_user(client) with mail.record_messages() as outbox: rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=user_info['email'], captcha='xyzzy')) message = outbox.pop() assert message.send_to == {user_info['email']} soup = BeautifulSoup(message.html, 'html.parser') token = soup.a['href'].split('/')[-1] rv = client.get(url_for('user.password_reset', token=token), follow_redirects=True) rv = client.post(url_for('do.reset'), data=dict(csrf_token=csrf_token(rv.data), user=get_value(rv.data, 'user'), key=get_value(rv.data, 'key'), password=new_password, confirm=new_password)) log_out_current_user(client) user_info['password'] = new_password log_in_user(client, user_info, expect_success=True)
def test_admin_can_ban_email_domain(client, user_info): register_user(client, user_info) promote_user_to_admin(client, user_info) rv = client.get(url_for('admin.domains', domain_type='email')) rv = client.post(url_for('do.ban_domain', domain_type='email'), data=dict(csrf_token=csrf_token(rv.data), domain='spam4u.com'), follow_redirects=True) reply = json.loads(rv.data.decode('utf-8')) assert reply['status'] == 'ok' log_out_current_user(client) rv = client.get(url_for('auth.register')) with mail.record_messages() as outbox: data = dict(csrf_token=csrf_token(rv.data), username='******', password='******', confirm='Safe123#$@lolnot', email_required='*****@*****.**', invitecode='', accept_tos=True, captcha='xyzzy') rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) assert len(outbox) == 0 assert b'do not accept emails' in rv.data assert b'Register' in rv.data assert b'Log out' not in rv.data
def test_admin_can_ban_and_unban_user(client, user_info, user2_info): register_user(client, user_info) register_user(client, user2_info) promote_user_to_admin(client, user2_info) username = user_info["username"] rv = client.get(url_for("user.view", user=username)) client.post( url_for("do.ban_user", username=username), data=dict(csrf_token=csrf_token(rv.data)), follow_redirects=True, ) # For now, banning makes you unable to log in. log_out_current_user(client) log_in_user(client, user_info, expect_success=False) log_in_user(client, user2_info) rv = client.get(url_for("user.view", user=username)) client.post( url_for("do.unban_user", username=username), data=dict(csrf_token=csrf_token(rv.data)), follow_redirects=True, ) log_out_current_user(client) log_in_user(client, user_info)
def test_send_and_receive_pm(client, user_info, user2_info): """Send and receive a private message.""" username = user_info["username"] register_user(client, user_info) register_user(client, user2_info) # User2 sends User a message. rv = client.get(url_for("user.view", user=username)) assert rv.status == "200 OK" client.post( url_for("do.create_sendmsg"), data=dict( csrf_token=csrf_token(rv.data), to=username, subject="Testing", content="Test Content", ), follow_redirects=True, ) # User2 sees the message in Sent Messages. rv = client.get(url_for("messages.view_messages_sent"), follow_redirects=True) assert rv.status == "200 OK" assert substrings_present(rv.data, [username, "Testing", "Test Content"]) log_out_current_user(client, verify=True) log_in_user(client, user_info, expect_success=True) # User has one new message. rv = client.get(url_for("home.index"), follow_redirects=True) assert rv.status == "200 OK" soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") link = soup.find(href=url_for("messages.inbox_sort")) assert link.get_text().strip() == "1" # User sees the message on the inbox page. rv = client.get(url_for("messages.inbox_sort"), follow_redirects=True) assert rv.status == "200 OK" assert substrings_present( rv.data, [user2_info["username"], "Testing", "Test Content"] ) # User marks the message as read. soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") tag = soup.find(lambda tag: tag.has_attr("data-mid")) mid = tag.attrs["data-mid"] rv = client.post( url_for("do.read_pm", mid=mid), data=dict(csrf_token=csrf_token(rv.data)), ) # User returns to home page; notifications count now 0. rv = client.get(url_for("home.index"), follow_redirects=True) assert rv.status == "200 OK" soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") link = soup.find(href=url_for("messages.inbox_sort")) assert link.get_text().strip() == "0"
def test_delete_account(client, user_info): """A user can delete their account.""" register_user(client, user_info) # The password has to be right. rv = client.get(url_for("user.delete_account")) rv = client.post( url_for("do.delete_user"), data=dict( csrf_token=csrf_token(rv.data), password="******", consent="YES", ), follow_redirects=True, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "error" # The consent must be given. rv = client.get(url_for("user.delete_account")) rv = client.post( url_for("do.delete_user"), data=dict( csrf_token=csrf_token(rv.data), password="******", consent="NO", ), follow_redirects=True, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "error" rv = client.get(url_for("user.delete_account")) rv = client.post( url_for("do.delete_user"), data=dict( csrf_token=csrf_token(rv.data), password=user_info["password"], consent="YES", ), follow_redirects=True, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Deleting your account should log you out. rv = client.get(url_for("home.index")) assert b"Log in" in rv.data # Try to log in to the deleted account. log_in_user(client, user_info, expect_success=False)
def test_resend_registration_email(client, user_info, test_config): """Registered but unconfirmed users can resend the registration link.""" rv = client.get(url_for("auth.register")) data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], email_required=user_info["email"], invitecode="", accept_tos=True, captcha="xyzzy", ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert b"spam" in rv.data # Telling user to go check it. # Find the resend link. soup = BeautifulSoup(rv.data, "html.parser") links = soup.find_all( lambda tag: tag.name == "a" and tag.string == "Resend") url = links[0]["href"] # Request the resend form and verify the registered email is shown. rv = client.get(url) assert b"Resend account confirmation instructions" in rv.data soup = BeautifulSoup(rv.data, "html.parser") tag = soup.find_all(lambda tag: tag.get("name") == "email")[0] assert tag["value"] == user_info["email"] # Use the resend form and the resent link. with mail.record_messages() as outbox: rv = client.post( url, data=dict( csrf_token=csrf_token(rv.data), email=user_info["email"], ), follow_redirects=True, ) assert b"spam" in rv.data # Telling user to go check it. message = outbox.pop() soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get(url_for("auth.login_with_token", token=token), follow_redirects=True) assert b"Log out" in rv.data
def test_reregister(client, user_info, user2_info, test_config): "A user account which is unconfirmed after two days can be re-registered." rv = client.get(url_for("auth.register")) data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], invitecode="", accept_tos=True, email_required=user_info["email"], captcha="xyzzy", ) client.post(url_for("auth.register"), data=data, follow_redirects=True) new_user = User.get(User.name == user_info["username"]) assert new_user.status == UserStatus.PROBATION new_user.joindate -= timedelta(days=3) new_user.save() rv = client.get(url_for("auth.register")) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], invitecode="", email_required=user2_info["email"], accept_tos=True, ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert b"spam" in rv.data # Telling user to go check it. message = outbox[-1] assert message.send_to == {user2_info["email"]} soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get( url_for("auth.login_with_token", token=token), follow_redirects=True ) assert b"Log out" in rv.data assert auth_provider.get_user_by_email(user_info["email"]) is None assert ( auth_provider.get_user_by_email(user2_info["email"]).name == user_info["username"] )
def test_submit_text_post(client, user_info, test_config): register_user(client, user_info) create_sub(client) rv = client.get(url_for("subs.submit", ptype="text", sub="test")) data = {"csrf_token": csrf_token(rv.data), "title": "f\u000A\u000A\u000A"} rv = client.post( url_for("subs.submit", ptype="text", sub="does_not_exist"), data=data, follow_redirects=True, ) assert b"Sub does not exist" in get_error(rv.data) rv = client.post( url_for("subs.submit", ptype="text", sub="test"), data=data, follow_redirects=True, ) assert b"Error in the 'Post type' field - This field is required." == get_error( rv.data) data["ptype"] = "text" rv = client.post( url_for("subs.submit", ptype="text", sub="test"), data=data, follow_redirects=True, ) assert b"Title is too short and/or contains whitespace characters." in get_error( rv.data) data["title"] = "Testing!" rv = client.post( url_for("subs.submit", ptype="text", sub="test"), data=data, follow_redirects=True, ) assert not get_error(rv.data) assert b"Testing! | test" in rv.data
def test_submit_link_post(client, user_info, test_config): register_user(client, user_info) create_sub(client) rv = client.get(url_for("subs.submit", ptype="text", sub="test")) data = { "csrf_token": csrf_token(rv.data), "title": "Testing link!", "ptype": "link", } rv = client.post( url_for("subs.submit", ptype="link", sub="test"), data=data, follow_redirects=False, ) assert get_error(rv.data) == b"No link provided." data["link"] = "https://google.com" rv = client.post( url_for("subs.submit", ptype="link", sub="test"), data=data, follow_redirects=False, ) assert rv.status_code == 302 assert "/s/test/1" == rv.location # Test anti-repost rv = client.post( url_for("subs.submit", ptype="link", sub="test"), data=data, follow_redirects=False, ) assert (get_error( rv.data ) == b'This link was <a href="/s/test/1">recently posted</a> on this sub.')
def test_admin_totp_auth_flow(client, user_info, test_config): register_user(client, user_info) assert client.get(url_for("admin.auth")).status_code == 404 promote_user_to_admin(client, user_info) rv = client.get(url_for("admin.auth"), follow_redirects=True) assert rv.status_code == 200 assert b"TOTP setup" in rv.data user = User.get(User.name == user_info["username"]) user_secret = UserMetadata.get((UserMetadata.uid == user.uid) & (UserMetadata.key == "totp_secret")) totp = pyotp.TOTP(user_secret.value) data = {"csrf_token": csrf_token(rv.data), "totp": totp.now()} rv = client.post(url_for("admin.auth"), data=data, follow_redirects=False) assert rv.status_code == 302 assert rv.location == url_for("admin.index") # Try again with bad token data["totp"] = "1" rv = client.post(url_for("admin.auth"), data=data, follow_redirects=False) assert rv.status_code == 200 assert b"Invalid or expired token." in rv.data # Check if we're actually logged in. assert client.get(url_for("admin.index")).status_code == 200 # Get QR code after we already set up TOTP assert client.get(url_for("admin.get_totp_image")).status_code == 403 # Try logging out. client.post(url_for("admin.logout"), data=data) assert client.get(url_for("admin.index"), follow_redirects=False).status_code == 302
def test_registration_login(client): """The registration page logs a user in if they register correctly.""" rv = client.get(url_for('auth.register')) with mail.record_messages() as outbox: data = dict(csrf_token=csrf_token(rv.data), username='******', password='******', confirm='Safe123#$@lolnot', invitecode='', accept_tos=True, captcha='xyzzy') if email_validation_is_required(): data['email_required'] = '*****@*****.**' else: data['email_optional'] = '*****@*****.**' rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) if email_validation_is_required(): assert b'spam' in rv.data # Telling user to go check it. message = outbox[-1] soup = BeautifulSoup(message.html, 'html.parser') token = soup.a['href'].split('/')[-1] rv = client.get(url_for('auth.login_with_token', token=token), follow_redirects=True) assert auth_provider.get_user_by_email( '*****@*****.**').name == 'supertester' assert b'Log out' in rv.data
def test_registration_login(client, test_config): """The registration page logs a user in if they register correctly.""" rv = client.get(url_for("auth.register")) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username="******", password="******", confirm="Safe123#$@lolnot", invitecode="", accept_tos=True, captcha="xyzzy", ) if email_validation_is_required(): data["email_required"] = "*****@*****.**" else: data["email_optional"] = "*****@*****.**" rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) if email_validation_is_required(): assert b"spam" in rv.data # Telling user to go check it. message = outbox[-1] soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get(url_for("auth.login_with_token", token=token), follow_redirects=True) assert auth_provider.get_user_by_email( "*****@*****.**").name == "supertester" assert b"Log out" in rv.data
def test_change_password(client, user_info): """A user can change their password and log in with the new password.""" register_user(client, user_info) new_password = "******" + "\N{PARTIAL DIFFERENTIAL}" assert new_password != user_info["password"] rv = client.get(url_for("user.edit_account")) rv = client.post( url_for("do.edit_account"), data=dict( csrf_token=csrf_token(rv.data), oldpassword=user_info["password"], password=new_password, confirm=new_password, ), follow_redirects=True, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" log_out_current_user(client) # Try to log in with the old password log_in_user(client, user_info, expect_success=False) new_info = dict(user_info) new_info.update(password=new_password) log_in_user(client, new_info, expect_success=True)
def test_login_before_confirming_email(client, user_info, test_config): """Registered users with unconfirmed emails can't log in.""" rv = client.get(url_for("auth.register")) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], email_required=user_info["email"], invitecode="", accept_tos=True, captcha="xyzzy", ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert b"spam" in rv.data # Telling user to go check it. message = outbox.pop() rv = client.get(url_for("auth.login")) rv = client.post( url_for("auth.login"), data=dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], ), follow_redirects=True, ) assert b"Resend account confirmation instructions" in rv.data rv = client.post( url_for("auth.resend_confirmation_email"), data=dict(csrf_token=csrf_token(rv.data), email=user_info["email"]), follow_redirects=True, ) assert b"spam" in rv.data # Telling user to go check it. message = outbox.pop() soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get(url_for("auth.login_with_token", token=token), follow_redirects=True) assert b"Log out" in rv.data
def test_password_required_to_change_recovery_email(client, user_info, test_config): """Changing the password recovery requires the correct password.""" register_user(client, user_info) wrong_password = "******" new_email = "*****@*****.**" assert wrong_password != user_info["password"] assert new_email != user_info["email"] rv = client.get(url_for("user.edit_account")) data = dict( csrf_token=csrf_token(rv.data), email_required=new_email, oldpassword=wrong_password, password="", confirm="", ) # No confirmation email should be sent. with mail.record_messages() as outbox: rv = client.post(url_for("do.edit_account"), data=data, follow_redirects=True) assert len(outbox) == 0 log_out_current_user(client) # Verify password recovery email goes to the right place. with mail.record_messages() as outbox: rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha="xyzzy"), ) assert len(outbox) == 0 rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict( csrf_token=csrf_token(rv.data), email=user_info["email"], captcha="xyzzy", ), ) assert len(outbox) == 1
def test_reregister(client, user_info, user2_info): "A user account which is unconfirmed after two days can be re-registered." rv = client.get(url_for('auth.register')) data = dict(csrf_token=csrf_token(rv.data), username=user_info['username'], password=user_info['password'], confirm=user_info['password'], invitecode='', accept_tos=True, email_required=user_info['email'], captcha='xyzzy') rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) new_user = User.get(User.name == user_info['username']) assert new_user.status == UserStatus.PROBATION new_user.joindate -= timedelta(days=3) new_user.save() rv = client.get(url_for('auth.register')) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username=user_info['username'], password=user_info['password'], confirm=user_info['password'], invitecode='', email_required=user2_info['email'], accept_tos=True, ) rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) assert b'spam' in rv.data # Telling user to go check it. message = outbox[-1] assert message.send_to == {user2_info['email']} soup = BeautifulSoup(message.html, 'html.parser') token = soup.a['href'].split('/')[-1] rv = client.get(url_for('auth.login_with_token', token=token), follow_redirects=True) assert b'Log out' in rv.data assert auth_provider.get_user_by_email(user_info['email']) == None assert (auth_provider.get_user_by_email( user2_info['email']).name == user_info['username'])
def test_login_before_confirming_email(client, user_info): """Registered users with unconfirmed emails can't log in.""" rv = client.get(url_for('auth.register')) with mail.record_messages() as outbox: data = dict(csrf_token=csrf_token(rv.data), username=user_info['username'], password=user_info['password'], confirm=user_info['password'], email_required=user_info['email'], invitecode='', accept_tos=True, captcha='xyzzy') rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) assert b'spam' in rv.data # Telling user to go check it. message = outbox.pop() rv = client.get(url_for('auth.login')) rv = client.post(url_for('auth.login'), data=dict(csrf_token=csrf_token(rv.data), username=user_info['username'], password=user_info['password']), follow_redirects=True) assert b'Resend account confirmation instructions' in rv.data rv = client.post(url_for('auth.resend_confirmation_email'), data=dict(csrf_token=csrf_token(rv.data), email=user_info['email']), follow_redirects=True) assert b'spam' in rv.data # Telling user to go check it. message = outbox.pop() soup = BeautifulSoup(message.html, 'html.parser') token = soup.a['href'].split('/')[-1] rv = client.get(url_for('auth.login_with_token', token=token), follow_redirects=True) assert b'Log out' in rv.data
def test_delete_account(client, user_info): """A user can delete their account.""" register_user(client, user_info) # The password has to be right. rv = client.get(url_for('user.delete_account')) rv = client.post(url_for('do.delete_user'), data=dict(csrf_token=csrf_token(rv.data), password='******', consent='YES'), follow_redirects=True) reply = json.loads(rv.data.decode('utf-8')) assert reply['status'] == 'error' # The consent must be given. rv = client.get(url_for('user.delete_account')) rv = client.post(url_for('do.delete_user'), data=dict(csrf_token=csrf_token(rv.data), password='******', consent='NO'), follow_redirects=True) reply = json.loads(rv.data.decode('utf-8')) assert reply['status'] == 'error' rv = client.get(url_for('user.delete_account')) rv = client.post(url_for('do.delete_user'), data=dict(csrf_token=csrf_token(rv.data), password=user_info['password'], consent='YES'), follow_redirects=True) reply = json.loads(rv.data.decode('utf-8')) assert reply['status'] == 'ok' # Deleting your account should log you out. rv = client.get(url_for('home.index')) assert b'Log in' in rv.data # Try to log in to the deleted account. log_in_user(client, user_info, expect_success=False)
def test_reset_password(client, user_info): """A user can reset their password using a link sent to their email.""" new_password = "******" assert new_password != user_info["password"] register_user(client, user_info) log_out_current_user(client) with mail.record_messages() as outbox: rv = client.get(url_for("user.password_recovery")) rv = client.post( url_for("user.password_recovery"), data=dict( csrf_token=csrf_token(rv.data), email=user_info["email"], captcha="xyzzy", ), ) message = outbox.pop() assert message.send_to == {user_info["email"]} soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get( url_for("user.password_reset", token=token), follow_redirects=True ) rv = client.post( url_for("do.reset"), data=dict( csrf_token=csrf_token(rv.data), user=get_value(rv.data, "user"), key=get_value(rv.data, "key"), password=new_password, confirm=new_password, ), ) log_out_current_user(client) user_info["password"] = new_password log_in_user(client, user_info, expect_success=True)
def test_password_required_to_change_recovery_email(client, user_info): """Changing the password recovery requires the correct password.""" register_user(client, user_info) wrong_password = '******' new_email = '*****@*****.**' assert wrong_password != user_info['password'] assert new_email != user_info['email'] rv = client.get(url_for('user.edit_account')) data = dict(csrf_token=csrf_token(rv.data), email_required=new_email, oldpassword=wrong_password, password='', confirm='') # No confirmation email should be sent. with mail.record_messages() as outbox: rv = client.post(url_for('do.edit_account'), data=data, follow_redirects=True) assert len(outbox) == 0 log_out_current_user(client) # Verify password recovery email goes to the right place. with mail.record_messages() as outbox: rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=new_email, captcha='xyzzy')) assert len(outbox) == 0 rv = client.get(url_for('user.password_recovery')) rv = client.post(url_for('user.password_recovery'), data=dict(csrf_token=csrf_token(rv.data), email=user_info['email'], captcha='xyzzy')) assert len(outbox) == 1
def test_create_sub_error(client, user_info): register_user(client, user_info) rv = client.get(url_for("subs.create_sub")) assert rv.status_code == 200 data = {"csrf_token": csrf_token(rv.data), "subname": "蛋糕", "title": "Testing"} rv = client.post(url_for("subs.create_sub"), data=data, follow_redirects=True) assert b"Sub name has invalid characters" in get_error(rv.data) data["subname"] = "home" rv = client.post(url_for("subs.create_sub"), data=data, follow_redirects=True) assert b"Invalid sub name" in get_error(rv.data) data["subname"] = "test" rv = client.post(url_for("subs.create_sub"), data=data, follow_redirects=True) assert b"You must be at least level 2." in get_error(rv.data)
def test_create_sub(client, user_info, test_config): register_user(client, user_info) rv = client.get(url_for("subs.create_sub")) assert rv.status_code == 200 data = {"csrf_token": csrf_token(rv.data), "subname": "test", "title": "Testing"} rv = client.post(url_for("subs.create_sub"), data=data, follow_redirects=True) assert not get_error(rv.data) assert b"/s/test" in rv.data # if we try again it should fail rv = client.post(url_for("subs.create_sub"), data=data, follow_redirects=True) assert b"Sub is already registered" == get_error(rv.data)
def test_submit_invalid_post_type(client, user_info, test_config): register_user(client, user_info) create_sub(client) rv = client.get(url_for("subs.submit", ptype="text", sub="test")) data = { "csrf_token": csrf_token(rv.data), "title": "Testing link!", } rv = client.post( url_for("subs.submit", ptype="toast", sub="test"), data=data, follow_redirects=False, ) assert rv.status_code == 404
def test_email_required_for_registration(client, user_info): "If emails are required, trying to register without one will fail." rv = client.get(url_for('auth.register')) with mail.record_messages() as outbox: data = dict(csrf_token=csrf_token(rv.data), username='******', password='******', confirm='Safe123#$@lolnot', email_required='', invitecode='', accept_tos=True, captcha='xyzzy') rv = client.post(url_for('auth.register'), data=data, follow_redirects=True) assert len(outbox) == 0 assert b'Error' in rv.data assert b'Register' in rv.data assert b'Log out' not in rv.data
def test_email_required_for_registration(client, user_info, test_config): """ If emails are required, trying to register without one will fail. """ rv = client.get(url_for("auth.register")) with mail.record_messages() as outbox: data = dict( csrf_token=csrf_token(rv.data), username="******", password="******", confirm="Safe123#$@lolnot", email_required="", invitecode="", accept_tos=True, captcha="xyzzy", ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert len(outbox) == 0 assert b"Error" in rv.data assert b"Register" in rv.data assert b"Log out" not in rv.data
def test_resend_registration_email_after_confirmation(client, user_info, test_config): """Registration instructions cannot be resent after confirmation.""" with mail.record_messages() as outbox: rv = client.get(url_for("auth.register")) data = dict( csrf_token=csrf_token(rv.data), username=user_info["username"], password=user_info["password"], confirm=user_info["password"], email_required=user_info["email"], invitecode="", accept_tos=True, captcha="xyzzy", ) rv = client.post(url_for("auth.register"), data=data, follow_redirects=True) assert b"spam" in rv.data # Telling user to go check it. # Find the resend link. soup = BeautifulSoup(rv.data, "html.parser") link = soup.find_all( lambda tag: tag.name == "a" and tag.string == "Resend")[0] url = link["href"] # Find and use the confirmation link. message = outbox[-1] soup = BeautifulSoup(message.html, "html.parser") token = soup.a["href"].split("/")[-1] rv = client.get(url_for("auth.login_with_token", token=token), follow_redirects=True) assert b"Log out" in rv.data log_out_current_user(client, verify=True) # Request the resend form and verify an error message is shown. rv = client.get(url, follow_redirects=True) assert b"The link you used is invalid or has expired" in rv.data assert b"Log out" not in rv.data
def test_change_password(client, user_info): """A user can change their password and log in with the new password.""" register_user(client, user_info) new_password = '******' + '\N{PARTIAL DIFFERENTIAL}' assert new_password != user_info['password'] rv = client.get(url_for('user.edit_account')) rv = client.post(url_for('do.edit_account'), data=dict(csrf_token=csrf_token(rv.data), oldpassword=user_info['password'], password=new_password, confirm=new_password), follow_redirects=True) reply = json.loads(rv.data.decode('utf-8')) assert reply['status'] == 'ok' log_out_current_user(client) # Try to log in with the old password log_in_user(client, user_info, expect_success=False) new_info = dict(user_info) new_info.update(password=new_password) log_in_user(client, new_info, expect_success=True)
def test_mod_invite_notification(client, user_info, user2_info): "Notifications are sent for mod invites." config.update_value("site.sub_creation_min_level", 0) receiver, mod = user_info, user2_info register_user(client, receiver) receiver_uid = User.get(User.name == receiver["username"]).uid log_out_current_user(client) register_user(client, mod) mod_uid = User.get(User.name == mod["username"]).uid create_sub(client, name="test_janitor") create_sub(client, name="test_mod") # Mod invites receiver as moderator. rv_index = client.get(url_for("home.index", sub="test_mod")) data = { "csrf_token": csrf_token(rv_index.data), "user": receiver["username"], "level": "1", } rv = client.post( url_for("do.inv_mod", sub="test_mod"), data=data, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Mod invites receiver as janitor. data = { "csrf_token": csrf_token(rv_index.data), "user": receiver["username"], "level": "2", } rv = client.post( url_for("do.inv_mod", sub="test_janitor"), data=data, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" log_out_current_user(client) # Receiver blocks mod. log_in_user(client, receiver) data = { "csrf_token": csrf_token(rv_index.data), "view_messages": "show", "view_content": "hide", } rv = client.post(url_for("do.edit_ignore", uid=mod_uid), data=data, follow_redirects=True) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Receiver checks notifications. They should not be ignored, # because they are mod actions. assert get_notification_count(receiver_uid)["notifications"] == 2 rv = client.get(url_for("messages.view_notifications")) assert b"invited you to moderate" in rv.data soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") assert soup.find(href=url_for("sub.edit_sub_mods", sub="test_mod")) assert soup.find(href=url_for("sub.edit_sub_mods", sub="test_janitor")) # After checking, the notification is marked read. assert get_notification_count(receiver_uid)["notifications"] == 0 # Receiver unblocks mod. data = { "csrf_token": csrf_token(rv.data), "view_messages": "show", "view_content": "show", } rv = client.post(url_for("do.edit_ignore", uid=mod_uid), data=data, follow_redirects=True) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Receiver checks notifications again. rv = client.get(url_for("messages.view_notifications")) assert b"invited you to moderate" in rv.data assert soup.find(href=url_for("sub.edit_sub_mods", sub="test_mod")) assert soup.find(href=url_for("sub.edit_sub_mods", sub="test_janitor"))
def test_post_delete_notification(client, user_info, user2_info, user3_info): "Notifications are sent for post delete and undelete." config.update_value("site.sub_creation_min_level", 0) receiver, admin, mod = user_info, user2_info, user3_info register_user(client, receiver) receiver_uid = User.get(User.name == receiver["username"]).uid log_out_current_user(client) register_user(client, admin) promote_user_to_admin(client, admin) log_out_current_user(client) register_user(client, mod) mod_uid = User.get(User.name == mod["username"]).uid create_sub(client) log_out_current_user(client) # Receiver makes a post. log_in_user(client, receiver) rv_post = client.get(url_for("subs.submit", ptype="text", sub="test")) csrf = csrf_token(rv_post.data) data = { "csrf_token": csrf, "title": "the title", "ptype": "text", "content": "the content", } rv = client.post( url_for("subs.submit", ptype="text", sub="test"), data=data, follow_redirects=False, ) assert rv.status == "302 FOUND" soup = BeautifulSoup(rv.data, "html.parser", from_encoding="utf-8") link = soup.a.get_text() pid = link.split("/")[-1] log_out_current_user(client) # Mod deletes the post. log_in_user(client, mod) data = { "csrf_token": csrf, "post": pid, "reason": "serious reason", "send_to_admin": False, } rv = client.post( url_for("do.delete_post"), data=data, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" log_out_current_user(client) # Admin un-deletes the post. log_in_user(client, admin) data = { "csrf_token": csrf, "post": pid, "reason": "frivolous reason", } rv = client.post( url_for("do.undelete_post"), data=data, ) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" log_out_current_user(client) # Receiver blocks mod. log_in_user(client, receiver) data = { "csrf_token": csrf, "view_messages": "show", "view_content": "hide", } rv = client.post(url_for("do.edit_ignore", uid=mod_uid), data=data, follow_redirects=True) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Receiver checks notifications. They should not be ignored, # because they are mod actions. assert get_notification_count(receiver_uid)["notifications"] == 2 rv = client.get(url_for("messages.view_notifications")) assert b" deleted your post" in rv.data assert b"un-deleted your post" in rv.data assert b"serious reason" in rv.data assert b"frivolous reason" in rv.data # After checking, the notification is marked read. assert get_notification_count(receiver_uid)["notifications"] == 0 # Receiver unblocks mod. data = { "csrf_token": csrf_token(rv.data), "view_messages": "show", "view_content": "show", } rv = client.post(url_for("do.edit_ignore", uid=mod_uid), data=data, follow_redirects=True) reply = json.loads(rv.data.decode("utf-8")) assert reply["status"] == "ok" # Receiver checks notifications again. rv = client.get(url_for("messages.view_notifications")) assert b" deleted your post" in rv.data assert b"un-deleted your post" in rv.data assert b"serious reason" in rv.data assert b"frivolous reason" in rv.data