From 8b061d643e340c43bbc2e839e30d19d67e272e41 Mon Sep 17 00:00:00 2001 From: Changaco Date: Mon, 18 Sep 2023 09:31:34 +0200 Subject: [PATCH] add more constraints on profile descriptions --- tests/py/test_profile_edit.py | 33 ++++++++++++------ www/%username/edit/statement.spt | 59 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/tests/py/test_profile_edit.py b/tests/py/test_profile_edit.py index c69bc64cf7..1d4739c394 100644 --- a/tests/py/test_profile_edit.py +++ b/tests/py/test_profile_edit.py @@ -1,37 +1,48 @@ from liberapay.testing import Harness +LOREM_IPSUM = ( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " + "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis " + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. " + "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " + "eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt " + "in culpa qui officia deserunt mollit anim id est laborum." +) + + class Tests(Harness): - def edit_statement(self, lang, statement, auth_as='alice', action='publish'): + def edit_statement(self, lang, statement, auth_as='alice', action='publish', summary=''): alice = self.make_participant('alice') return self.client.POST( "/alice/edit/statement", - {'lang': lang, 'statement': statement, 'action': action}, + {'lang': lang, 'statement': statement, 'summary': summary, 'action': action}, auth_as=alice if auth_as == 'alice' else auth_as, raise_immediately=False ) def test_anonymous_gets_403(self): - r = self.edit_statement('en', 'Some statement', auth_as=None) + r = self.edit_statement('en', LOREM_IPSUM, auth_as=None) assert r.code == 403 def test_participant_can_change_their_statement(self): - r = self.edit_statement('en', 'Lorem ipsum') + r = self.edit_statement('en', LOREM_IPSUM) assert r.code == 302 r = self.client.GET('/alice/') - assert '

Lorem ipsum

' in r.text, r.text + assert LOREM_IPSUM in r.text, r.text def test_participant_can_preview_their_statement(self): - r = self.edit_statement('en', 'Lorem ipsum', action='preview') + r = self.edit_statement('en', LOREM_IPSUM, action='preview') assert r.code == 200 - assert '

Lorem ipsum

' in r.text, r.text + assert LOREM_IPSUM in r.text, r.text def test_participant_can_switch_language(self): alice = self.make_participant('alice') r = self.client.PxST( "/alice/edit/statement", - {'lang': 'en', 'switch_lang': 'fr', 'statement': '', 'action': 'switch'}, + {'lang': 'en', 'switch_lang': 'fr', 'statement': '', 'summary': '', + 'action': 'switch'}, auth_as=alice ) assert r.code == 302 @@ -41,14 +52,16 @@ def test_participant_is_warned_of_unsaved_changes_when_switching_language(self): alice = self.make_participant('alice') r = self.client.POST( "/alice/edit/statement", - {'lang': 'en', 'switch_lang': 'fr', 'statement': 'foo', 'action': 'switch'}, + {'lang': 'en', 'switch_lang': 'fr', 'statement': 'foo', 'summary': '', + 'action': 'switch'}, auth_as=alice ) assert r.code == 200 assert " are you sure you want to discard them?" in r.text, r.text r = self.client.PxST( "/alice/edit/statement", - {'lang': 'en', 'switch_lang': 'fr', 'statement': 'foo', 'action': 'switch', 'discard': 'yes'}, + {'lang': 'en', 'switch_lang': 'fr', 'statement': 'foo', 'summary': '', + 'action': 'switch', 'discard': 'yes'}, auth_as=alice ) assert r.code == 302 diff --git a/www/%username/edit/statement.spt b/www/%username/edit/statement.spt index 58e3c31936..589d2f1ebe 100644 --- a/www/%username/edit/statement.spt +++ b/www/%username/edit/statement.spt @@ -4,32 +4,47 @@ from liberapay.utils import excerpt_intro, form_post_success, get_participant, m [---] participant = get_participant(state, restrict=True, allow_member=True) +errors = [] + if request.method == 'POST': lang = request.body['lang'] switch_lang = request.body.get('switch_lang') - summary = request.body.get('summary') or '' - statement = request.body['statement'] - - action = request.body.get('action') - if action is None: - # Temporary fallback - if request.body.get('save') == 'true': - action = 'publish' - elif request.body.get('preview') == 'true': - action = 'preview' - else: - action = 'edit' + summary = request.body['summary'].strip() + statement = request.body['statement'].strip() + action = request.body.get_choice('action', ('edit', 'preview', 'publish', 'switch')) if lang not in ACCEPTED_LANGUAGES: raise response.invalid_input(lang, 'lang', 'body') if switch_lang and switch_lang not in ACCEPTED_LANGUAGES: raise response.invalid_input(lang, 'switch_lang', 'body') - if len(summary) > constants.SUMMARY_MAX_SIZE: - raise response.error(400, _( - "The submitted summary is too long ({0} > {1}).", - len(summary), constants.SUMMARY_MAX_SIZE) - ) + if action != 'switch': + if len(summary) > constants.SUMMARY_MAX_SIZE: + errors.append(ngettext( + "", + "The summary can't be more than {n} characters long.", + constants.SUMMARY_MAX_SIZE + )) + if len(statement) < 100: + errors.append(ngettext( + "", + "The full description must be at least {n} characters long.", + n=100 + )) + elif len(statement) > 50_000: + errors.append(ngettext( + "", + "The full description can't be more than {n} characters long.", + n=50_000 + )) + if statement and statement == summary: + errors.append(_("The full description can't be identical to the summary.")) + if summary in (participant.username, participant.public_name): + errors.append(_("The summary can't be only your name.")) + if statement in (participant.username, participant.public_name): + errors.append(_("The description can't be only your name.")) + if errors: + action = 'edit' if action == 'publish': participant.upsert_statement(lang, summary, 'summary') @@ -83,8 +98,9 @@ subhead = _("Descriptions")
-

{{ _("Statement") }}

+ +

{{ _("Description") }}

{{ rendered_stmt }}

{{ _("Excerpt that will be used in social media:") }}

@@ -92,7 +108,6 @@ subhead = _("Descriptions")
% if summary

{{ _("Preview of the short description") }}

- {{ profile_box_embedded(participant, summary) }}
% if participant.username in summary @@ -120,9 +135,7 @@ subhead = _("Descriptions") - % if summary - % endif
@@ -133,6 +146,10 @@ subhead = _("Descriptions") % else + % for error in errors +

{{ error }}

+ % endfor +

{{ _( "Describe your work, why you're asking for donations, etc. The short " "summary will be used when showcasing your profile alongside others, "