Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source Interface: Flow Inversion #6438

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 21 additions & 19 deletions securedrop/sass/source.sass
Expand Up @@ -43,9 +43,6 @@ h1, h2, h3, h4
h1, h2
font-size: 24px

#source-lookup h2
font-size: 18px

p
margin: 0 0 12px 0

Expand Down Expand Up @@ -211,7 +208,7 @@ header
width: 150px
padding-top: 60px - 17px
padding-bottom: 30px
margin: 0 30px 0 15px
margin: 0 30px 0 25px

#source-index
.content
Expand Down Expand Up @@ -473,18 +470,18 @@ mark
background: $passphrase_masked_color
clip-path: polygon(0% 0%, 0% 100%, 20% 100%, 20% 0%, 23% 0%, 23% 100%, 32% 100%, 32% 0%, 35% 0%, 35% 100%, 42% 100%, 42% 0%, 45% 0%, 45% 100%, 64% 100%, 64% 0%, 67% 0%, 67% 100%, 74% 100%, 74% 0%, 77% 0%, 77% 100%, 90% 100%, 90% 0%, 93% 0%, 93% 100%, 100% 100%, 100% 0%)

#codename-reminder
#passphrase-reminder
font-size: 18px
color: $heading_alt_color

#codename-show-checkbox
#passphrase-show-checkbox
position: absolute
@include ltr
left: -999rem
@include rtl
right: -999rem

&~ #codename-show
&~ #passphrase-show
font-size: 11px
line-height: 14px
margin-top: -2px
Expand All @@ -501,7 +498,7 @@ mark
border-color: $checkbox_hover_border
box-shadow: inset 0 0 0 1px $checkbox_hover_border_inside

@mixin codename-show-checkbox
@mixin passphrase-show-checkbox
content: ""
background: $body_bg
display: block
Expand All @@ -511,10 +508,10 @@ mark

&::before
@include ltr
@include codename-show-checkbox
@include passphrase-show-checkbox
&::after
@include rtl
@include codename-show-checkbox
@include passphrase-show-checkbox

&::before
@include ltr
Expand All @@ -525,7 +522,7 @@ mark
margin-left: 12px
float: right

&:focus-visible ~ #codename-show
&:focus-visible ~ #passphrase-show
box-shadow: 0 0 0 3px $focus_shadow

&:checked ~ mark > span
Expand All @@ -543,14 +540,14 @@ mark
height: 13px
border: 0

&:checked ~ #codename-show::before
&:checked ~ #passphrase-show::before
@include ltr
@include checked
&:checked ~ #codename-show::after
&:checked ~ #passphrase-show::after
@include rtl
@include checked

#codename-show
#passphrase-show
display: block

#upload
Expand Down Expand Up @@ -944,18 +941,23 @@ header img, #locales-menu, #locales-menu-list

main
width: calc(100% - 210px)
border: 1px solid $main_border
padding: 50px 30px 24px 30px
padding: 50px 20px 0 15px

section[aria-labelledby="submit-heading"]
clear: both

section[aria-labelledby="codename-reminder"] + section h2
section[aria-labelledby="welcome-heading"]
margin-top: 50px

section[aria-labelledby="passphrase-reminder"] + section h2
padding-top: 26px

#source-lookup main, #source-logout main
padding-top: 22px

#source-lookup #encrypt-before-sending
display: none

#source-logout main nav + section
margin-top: 44px

Expand Down Expand Up @@ -1138,11 +1140,11 @@ section[aria-labelledby="codename-reminder"] + section h2
.info
padding: 9px

#flashed + section, #codename-hint + section:not(#flashed)
#flashed + section, #passphrase-hint + section:not(#flashed)
margin-top: 3em

#source-lookup nav + section:not(#flashed)
margin-top: 53px
margin-top: 47px

nav + section#flashed
margin-top: -1em
Expand Down
39 changes: 30 additions & 9 deletions securedrop/source_app/decorators.py
Expand Up @@ -3,28 +3,49 @@
from db import db

from flask import redirect, url_for, request, session
import werkzeug
from functools import wraps

from typing import Callable
from typing import Callable, Union, Optional

from source_app.utils import clear_session_and_redirect_to_logged_out_page
from source_app.session_manager import SessionManager, UserNotLoggedIn, \
UserSessionExpired, UserHasBeenDeleted
from source_user import SourceUser


def login_required(f: Callable) -> Callable:
def _source_user() -> Optional[Union[SourceUser, werkzeug.Response]]:
try:
return SessionManager.get_logged_in_user(db_session=db.session)

except (UserSessionExpired, UserHasBeenDeleted):
return clear_session_and_redirect_to_logged_out_page(flask_session=session)

except UserNotLoggedIn:
return None


def login_possible(f: Callable) -> Callable:
@wraps(f)
def decorated_function(*args: Any, **kwargs: Any) -> Any:
try:
logged_in_source = SessionManager.get_logged_in_user(db_session=db.session)
def decorated_function(*args: Any, **kwargs: Any) -> Union[str, werkzeug.Response]:
result = _source_user()
if isinstance(result, werkzeug.Response):
return result

return f(*args, **kwargs, logged_in_source=result)
return decorated_function

except (UserSessionExpired, UserHasBeenDeleted):
return clear_session_and_redirect_to_logged_out_page(flask_session=session)

except UserNotLoggedIn:
def login_required(f: Callable) -> Callable:
@wraps(f)
def decorated_function(*args: Any, **kwargs: Any) -> Union[str, werkzeug.Response]:
result = _source_user()
if result is None:
return redirect(url_for("main.login"))
elif isinstance(result, werkzeug.Response):
return result

return f(*args, **kwargs, logged_in_source=logged_in_source)
return f(*args, **kwargs, logged_in_source=result)
return decorated_function


Expand Down
20 changes: 9 additions & 11 deletions securedrop/source_app/forms.py
Expand Up @@ -11,14 +11,15 @@

class LoginForm(FlaskForm):

codename = PasswordField('codename', validators=[
passphrase = PasswordField('passphrase', validators=[
InputRequired(message=gettext('This field is required.')),
Length(1, PassphraseGenerator.MAX_PASSPHRASE_LENGTH,
message=gettext(
'Field must be between 1 and '
'{max_codename_len} characters long.'.format(
max_codename_len=PassphraseGenerator.MAX_PASSPHRASE_LENGTH))),
'{max_passphrase_len} characters long.'.format(
max_passphrase_len=PassphraseGenerator.MAX_PASSPHRASE_LENGTH))),
# Make sure to allow dashes since some words in the wordlist have them
# TODO
Regexp(r'[\sA-Za-z0-9-]+$', message=gettext('Invalid input.'))
])

Expand All @@ -31,15 +32,12 @@ class SubmissionForm(FlaskForm):

def validate_msg(self, field: wtforms.Field) -> None:
if len(field.data) > Submission.MAX_MESSAGE_LEN:
message = gettext("Message text too long.")
err = gettext("The message you submit can be at most "
"{} characters long.").format(Submission.MAX_MESSAGE_LEN)
if InstanceConfig.get_default().allow_document_uploads:
message = "{} {}".format(
message,
gettext(
"Large blocks of text must be uploaded as a file, not copied and pasted."
)
)
raise ValidationError(message)
err = "{} {}".format(err, gettext("If you need to submit large blocks of text, "
"you can upload them as a file."))
raise ValidationError(err)

def validate_antispam(self, field: wtforms.Field) -> None:
"""If the antispam field has any contents, abort with a 403"""
Expand Down