Skip to content

Commit 3fc4feb

Browse files
committed
Address review: raise NotImplementedError in csrf noop, fix mypy errors
1 parent 1f6d824 commit 3fc4feb

4 files changed

Lines changed: 32 additions & 20 deletions

File tree

config/graphql/analysis_mutations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,5 @@ def mutate(root, info, id) -> "DeleteAnalysisMutation":
206206

207207
# Kick off an async task to delete the analysis (as it can be very large)
208208
delete_analysis_and_annotations_task.si(analysis_pk=analysis_pk).apply_async()
209+
210+
return DeleteAnalysisMutation(ok=True, message="SUCCESS")

config/graphql/pipeline_queries.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from __future__ import annotations
66

77
import logging
8-
from collections.abc import Sequence
8+
from collections.abc import Mapping, Sequence
99
from typing import Optional
1010

1111
import graphene
@@ -45,7 +45,7 @@ class PipelineQueryMixin:
4545
def resolve_pipeline_components(
4646
self,
4747
info: graphene.ResolveInfo,
48-
mimetype: Optional[FileTypeEnum] = None,
48+
mimetype: FileTypeEnum | None = None,
4949
) -> PipelineComponentsType:
5050
"""
5151
Resolver for the pipeline_components query.
@@ -60,7 +60,7 @@ def resolve_pipeline_components(
6060
Returns:
6161
PipelineComponentsType: The pipeline components grouped by type.
6262
"""
63-
components_data: dict[str, Sequence[PipelineComponentDefinition]]
63+
components_data: Mapping[str, Sequence[PipelineComponentDefinition]]
6464
if mimetype:
6565
mime_type_str = FILE_TYPE_TO_MIME.get(mimetype.value)
6666
if mime_type_str is None:
@@ -131,7 +131,7 @@ def to_graphql_type(
131131
defn: PipelineComponentDefinition, component_type: str
132132
) -> PipelineComponentType:
133133
is_enabled = (not enabled_set) or (defn.class_name in enabled_set)
134-
settings_schema: Optional[list[ComponentSettingSchemaType]] = None
134+
settings_schema: list[ComponentSettingSchemaType] | None = None
135135
if user.is_superuser:
136136
# Get schema augmented with has_value/current_value from DB
137137
augmented_schema = settings_instance.get_component_schema(

config/graphql/security.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030

3131
def _csrf_noop_get_response(request: HttpRequest) -> HttpResponse:
3232
# CsrfViewMiddleware only invokes ``get_response`` when we call
33-
# ``__call__``; we only use ``process_view``, so this is never reached.
34-
# An empty ``HttpResponse`` keeps the middleware's type contract happy.
35-
return HttpResponse()
33+
# ``__call__``; we only use ``process_view``, so this is unreachable.
34+
raise NotImplementedError(
35+
"_csrf_noop_get_response is unreachable: CsrfViewMiddleware.process_view "
36+
"does not call get_response."
37+
)
3638

3739

3840
_csrf_middleware = CsrfViewMiddleware(_csrf_noop_get_response)

opencontractserver/utils/permissioning.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323

2424
def set_permissions_for_obj_to_user(
25-
user_val: int | str | "UserModel",
25+
user_val: int | str | UserModel,
2626
instance: django.db.models.Model,
2727
permissions: list[PermissionTypes],
2828
) -> None:
@@ -167,7 +167,7 @@ def set_permissions_for_obj_to_user(
167167
assign_perm(f"{app_name}.publish_{model_name}", user, instance)
168168

169169

170-
def get_users_group_ids(user_instance: "UserModel") -> list[str | int]:
170+
def get_users_group_ids(user_instance: UserModel) -> list[str | int]:
171171
"""
172172
For a given user, return list of group ids it belongs to.
173173
"""
@@ -206,7 +206,7 @@ def get_permission_id_to_name_map_for_model(
206206

207207

208208
def get_users_permissions_for_obj(
209-
user: "UserModel",
209+
user: UserModel,
210210
instance: django.db.models.Model,
211211
include_group_permissions: bool = False,
212212
) -> set[str]:
@@ -304,7 +304,7 @@ def get_users_permissions_for_obj(
304304

305305

306306
def user_has_permission_for_obj(
307-
user_val: int | str | "UserModel",
307+
user_val: int | str | UserModel,
308308
instance: django.db.models.Model,
309309
permission: PermissionTypes,
310310
include_group_permissions: bool = False,
@@ -383,10 +383,10 @@ def user_has_permission_for_obj(
383383
# For private annotations, permissions are limited by BOTH the source object AND doc+corpus
384384
# We need to check the source object permissions match or exceed what's being requested
385385
if instance.created_by_analysis_id:
386-
# Check if user has the requested permission level on the analysis
387-
if not user_has_permission_for_obj(
386+
source_analysis = instance.created_by_analysis
387+
if source_analysis is None or not user_has_permission_for_obj(
388388
user,
389-
instance.created_by_analysis,
389+
source_analysis,
390390
permission, # Check for the same permission level being requested
391391
include_group_permissions=include_group_permissions,
392392
):
@@ -396,10 +396,10 @@ def user_has_permission_for_obj(
396396
)
397397
return False
398398
elif instance.created_by_extract_id:
399-
# Check if user has the requested permission level on the extract
400-
if not user_has_permission_for_obj(
399+
source_extract = instance.created_by_extract
400+
if source_extract is None or not user_has_permission_for_obj(
401401
user,
402-
instance.created_by_extract,
402+
source_extract,
403403
permission, # Check for the same permission level being requested
404404
include_group_permissions=include_group_permissions,
405405
):
@@ -409,7 +409,11 @@ def user_has_permission_for_obj(
409409
)
410410
return False
411411

412-
# Now check document+corpus permissions using the query optimizer
412+
# Now check document+corpus permissions using the query optimizer.
413+
# An annotation without a parent document has no inheritable scope,
414+
# so non-superuser access is denied (the superuser branch is above).
415+
if instance.document_id is None:
416+
return False
413417
can_read, can_create, can_update, can_delete, can_comment = (
414418
AnnotationQueryOptimizer._compute_effective_permissions(
415419
user=user,
@@ -467,8 +471,12 @@ def user_has_permission_for_obj(
467471
)
468472
return False
469473

470-
# Relationships inherit permissions from document+corpus
471-
# Use the same logic as annotations
474+
# Relationships inherit permissions from document+corpus.
475+
# Relationships without a document have no inheritable scope, so
476+
# we deny all non-superuser access (the superuser short-circuit
477+
# above is the only escape).
478+
if instance.document_id is None:
479+
return False
472480
can_read, can_create, can_update, can_delete, can_comment = (
473481
AnnotationQueryOptimizer._compute_effective_permissions(
474482
user=user,

0 commit comments

Comments
 (0)