Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion airlock/templates/file_browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@
{% endfragment %}

{% #card title=title custom_button=action_button %}

{% if context == "request" %}
{% #description_item title="Status:" %}{{ release_request.status.name }}{% /description_item %}
{% endif %}
Expand Down
9 changes: 0 additions & 9 deletions airlock/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@

{% block metatitle %}Login | OpenSAFELY Airlock{% endblock metatitle %}

{% block breadcrumbs %}
{% url "home" as home_url %}

{% #breadcrumbs %}
{% breadcrumb title="Home" url=home_url %}
{% breadcrumb title="Login" active=True %}
{% /breadcrumbs %}
{% endblock breadcrumbs %}

{% block content %}
<section class="flex flex-col max-w-2xl gap-y-4">
<h1 class="text-3xl break-words font-bold text-slate-900 mt-2 md:mt-0 md:col-span-3 md:text-4xl">
Expand Down
4 changes: 3 additions & 1 deletion airlock/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ def login(request):

if request.method != "POST":
next_url = request.GET.get("next", default_next_url)
if request.user is not None:
return redirect(next_url)
token_login_form = TokenLoginForm()
else:
next_url = request.POST.get("next", default_next_url)
Expand Down Expand Up @@ -300,7 +302,7 @@ def request_release_files(request, request_id):
except api.RequestPermissionDenied as exc:
raise PermissionDenied(str(exc))
except requests.HTTPError as err:
if settings.DEBUG: # pragma: nocover
if settings.DEBUG:
return TemplateResponse(
request,
"jobserver-error.html",
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ exclude_also = [
# this indicates that a method should be defined in a subclass
"raise NotImplementedError",
]

[tool.coverage.django_coverage_plugin]
template_extensions = "html"
exclude_blocks = [
"\\/\\w+"
]
3 changes: 3 additions & 0 deletions requirements.dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ pytest-cov
pytest-django
pytest-playwright
responses
# Currently using our fork of django_coverage_plugin, pending
# upstream PR https://github.com/nedbat/django_coverage_plugin/pull/93
https://github.com/opensafely-core/django_coverage_plugin/archive/153a0ca6c02f7f01831568a546c848c4a3f082cd.zip
3 changes: 3 additions & 0 deletions requirements.dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ coverage==7.4.0 \
# via
# coverage
# pytest-cov
django-coverage-plugin @ https://github.com/opensafely-core/django_coverage_plugin/archive/153a0ca6c02f7f01831568a546c848c4a3f082cd.zip \
--hash=sha256:db70db8737dd269c346f7af6e0c735a3d6462b944302f6bc0178c7bac9a4c7ee
# via -r requirements.dev.in
greenlet==3.0.3 \
--hash=sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67 \
--hash=sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6 \
Expand Down
6 changes: 5 additions & 1 deletion tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ def write_request_file(request, path, contents=""):
path.write_text(contents)


def create_filegroup(release_request, group_name):
def create_filegroup(release_request, group_name, filepaths=None):
for filepath in filepaths or []:
api.add_file_to_request(
release_request, filepath, User(1, release_request.author), group_name
)
return api._get_or_create_filegroupmetadata(release_request.id, group_name)


Expand Down
16 changes: 16 additions & 0 deletions tests/integration/test_auth_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
pytestmark = pytest.mark.django_db


def test_login_get(client):
response = client.get("/login/")
assert response.status_code == 200
assert "token_login_form" in response.context


def test_login_already_logged_in(client):
session_user = {"id": 1, "username": "test"}
session = client.session
session["user"] = session_user
session.save()
response = client.get("/login/")
assert response.status_code == 302
assert response.url == ("/workspaces/")


@mock.patch("airlock.login_api.requests.post", autospec=True)
def test_login(requests_post, client, settings):
settings.AIRLOCK_API_TOKEN = "test_api_token"
Expand Down
91 changes: 90 additions & 1 deletion tests/integration/test_views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from io import BytesIO

import pytest
import requests
from django.contrib import messages
Expand Down Expand Up @@ -64,6 +66,14 @@ def test_workspace_view_with_file(client_with_permission, ui_options):
assert "foobar" in response.rendered_content


def test_workspace_view_with_html_file(client_with_permission, ui_options):
factories.write_workspace_file(
"workspace", "file.html", "<html><body>foobar</body></html>"
)
response = client_with_permission.get("/workspaces/view/workspace/file.html")
assert "foobar" in response.rendered_content


def test_workspace_view_with_404(client_with_permission):
factories.create_workspace("workspace")
response = client_with_permission.get("/workspaces/view/workspace/no_such_file.txt")
Expand All @@ -78,6 +88,14 @@ def test_workspace_view_redirects_to_directory(client_with_permission):
assert response.headers["Location"] == "/workspaces/view/workspace/some_dir/"


def test_workspace_view_directory_with_sub_directory(client_with_permission):
workspace = factories.create_workspace("workspace")
factories.write_workspace_file(workspace, "sub_dir/file.txt")
response = client_with_permission.get("/workspaces/view/workspace", follow=True)
assert "sub_dir" in response.rendered_content
assert "file.txt" in response.rendered_content


def test_workspace_view_redirects_to_file(client_with_permission):
factories.write_workspace_file("workspace", "file.txt")
response = client_with_permission.get("/workspaces/view/workspace/file.txt/")
Expand Down Expand Up @@ -305,13 +323,45 @@ def test_request_view_with_directory(client_with_permission, ui_options):

def test_request_view_with_file(client_with_permission, ui_options):
release_request = factories.create_release_request("workspace")
factories.write_request_file(release_request, "file.txt", "foobar")
factories.write_workspace_file("workspace", "file.txt", "foobar")
factories.create_filegroup(
release_request, group_name="default_group", filepaths=["file.txt"]
)

response = client_with_permission.get(
f"/requests/view/{release_request.id}/file.txt"
)
assert "default_group" in response.rendered_content
assert "foobar" in response.rendered_content


def test_request_view_with_submitted_request(client_with_permission, ui_options):
release_request = factories.create_release_request(
"workspace", status=Status.SUBMITTED
)
response = client_with_permission.get(
f"/requests/view/{release_request.id}", follow=True
)
assert "Reject Request" in response.rendered_content
assert "Release Files" in response.rendered_content


def test_request_view_with_authored_request_file(client_with_permission, ui_options):
release_request = factories.create_release_request(
"workspace",
user=User.from_session(client_with_permission.session),
status=Status.SUBMITTED,
)
factories.write_workspace_file("workspace", "file.txt", "foobar")
factories.create_filegroup(
release_request, group_name="default_group", filepaths=["file.txt"]
)
response = client_with_permission.get(
f"/requests/view/{release_request.id}/file.txt", follow=True
)
assert "Remove this file" in response.rendered_content


def test_request_view_with_404(client_with_permission):
release_request = factories.create_release_request("workspace")
response = client_with_permission.get(
Expand Down Expand Up @@ -499,6 +549,45 @@ def test_requests_release_jobserver_403(client_with_permission, release_files_st
assert response.status_code == 403


@pytest.mark.parametrize(
"content_type,content,should_contain_iframe",
[
("text/plain", b"An error from job-server", False),
("text/html", b"<p>An error from job-server</p>", True),
],
)
def test_requests_release_jobserver_403_with_debug(
client_with_permission,
release_files_stubber,
settings,
content_type,
content,
should_contain_iframe,
):
settings.DEBUG = True
release_request = factories.create_release_request(
"workspace",
id="request_id",
status=Status.SUBMITTED,
)
factories.write_request_file(release_request, "test/file.txt", "test")

response = requests.Response()
response.status_code = 403
response.headers = {"Content-Type": content_type}
response.raw = BytesIO(content)
api403 = requests.HTTPError(response=response)
release_files_stubber(release_request, body=api403)

# test 403 is handled
response = client_with_permission.post("/requests/release/request_id")
# DEBUG is on, so we return the job-server error
assert response.status_code == 200
assert "An error from job-server" in response.rendered_content
contains_iframe = "<iframe" in response.rendered_content
assert contains_iframe == should_contain_iframe


def test_requests_release_files_404(client_with_permission, release_files_stubber):
release_request = factories.create_release_request(
"workspace",
Expand Down