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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [7.0.2] - 10 June 2026

### Fixed

* Fixed evidence listings inside the collab editor for privileged users
* The list of evidence could appear empty for admins and managers if they were not assigned to the related project
* Permissions checked for project data access via invites and assignments, but missed access from the privileged roles

Comment thread
chrismaddalena marked this conversation as resolved.
## [7.0.1] - 10 June 2026

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
v7.0.1
v7.0.2
10 June 2026
2 changes: 1 addition & 1 deletion config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# 3rd Party Libraries
import environ

__version__ = "7.0.1"
__version__ = "7.0.2"
VERSION = __version__
RELEASE_DATE = "10 June 2026"

Expand Down
21 changes: 21 additions & 0 deletions ghostwriter/api/tests/test_hasura_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,32 @@ def user_feature_flag_check(flag_name):
}


def privileged_user_filter():
return {
"_exists": {
"_table": {"name": "users_user", "schema": "public"},
"_where": {
"_and": [
{"id": {"_eq": USER_ID_HEADER}},
{"is_active": {"_eq": True}},
{
"_or": [
{"role": {"_in": ["admin", "manager"]}},
{"is_staff": {"_eq": True}},
]
},
]
},
}
}


def collab_evidence_filter():
return {
"_and": [
{
"_or": [
privileged_user_filter(),
user_project_access_filter("finding", "report", "project"),
user_project_access_filter("report", "project"),
]
Expand Down
12 changes: 12 additions & 0 deletions ghostwriter/home/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,18 @@ def test_view_uri_exists_at_desired_location(self):
response = self.client_auth.get(self.uri)
self.assertEqual(response.status_code, 200)

def test_view_handles_assignment_without_dates(self):
ProjectAssignmentFactory(
project=self.future_project,
operator=self.user,
start_date=None,
end_date=None,
)

response = self.client_auth.get(self.uri)

self.assertEqual(response.status_code, 200)

def test_view_requires_login(self):
response = self.client.get(self.uri)
self.assertEqual(response.status_code, 302)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,5 @@

{% block morescripts %}
{{ block.super }}
<script type="text/plain" id="graphql-evidence-report-id">{{object.report.id}}</script>
<script type="text/plain" id="graphql-evidence-finding-id">{{object.id}}</script>
<script type="text/plain" id="graphql-evidence-upload-url">{% url 'reporting:upload_evidence' 'finding' object.id %}</script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@

{% block morescripts %}
{{ block.super }}
<script type="text/plain" id="graphql-evidence-report-id">{{object.report.id}}</script>
<script type="text/plain" id="graphql-evidence-upload-url">{% url 'reporting:upload_evidence' 'report' object.report.id %}</script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ <h2>{{ target_field.display_name}} on {{ report }}</h2>
{% block morescripts %}
{{ block.super }}
{{ report_oplogs|json_script:"report-oplog-options" }}
<script type="text/plain" id="graphql-evidence-report-id">{{object.id}}</script>
<script type="text/plain" id="graphql-evidence-upload-url">{% url 'reporting:upload_evidence' 'report' object.id %}</script>
<script type="text/plain" id="report-oplog-outline-url">{% url 'reporting:report_generate_oplog_outline' object.id %}</script>
{% endblock %}
2 changes: 2 additions & 0 deletions ghostwriter/rolodex/templatetags/determine_primary.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ def plus_days(value, days):
``days``
A whole integer to add to the day value of a ``datetime`` value
"""
if value is None:
return value
return value + datetime.timedelta(days=days)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,23 @@ select_permissions:
filter:
_and:
- _or:
- _exists:
_table:
name: users_user
schema: public
_where:
_and:
- id:
_eq: X-Hasura-User-Id
- is_active:
_eq: true
- _or:
- role:
_in:
- admin
- manager
- is_staff:
_eq: true
- finding:
report:
project:
Expand Down
27 changes: 2 additions & 25 deletions javascript/src/frontend/graphql/evidence.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useQuery } from "@apollo/client";
import { gql } from "../../__generated__/";
import { Evidence_Bool_Exp } from "../../__generated__/graphql";
import { useCallback, useMemo } from "react";
import { useCallback } from "react";
import { Evidences, EvidencesContext } from "../../tiptap_gw/evidence";

const QUERY_EVIDENCE = gql(`
Expand All @@ -13,31 +12,9 @@ const QUERY_EVIDENCE = gql(`
`);

export function usePageEvidence(): Evidences | null {
const filters: Evidence_Bool_Exp["_or"] = useMemo(() => {
const reportId = parseInt(
document.getElementById("graphql-evidence-report-id")!.innerHTML
);
const findingIdText = document.getElementById(
"graphql-evidence-finding-id"
)?.innerHTML;
const filters: Evidence_Bool_Exp["_or"] = [
{
reportId: { _eq: reportId },
},
];
if (findingIdText !== undefined) {
filters.push({
findingId: { _eq: +findingIdText },
});
}
return filters;
}, []);

const { data, refetch } = useQuery(QUERY_EVIDENCE, {
variables: {
where: {
_or: filters,
},
where: {},
},
pollInterval: 10000,
});
Expand Down