arize-phoenix 12.4.0__py3-none-any.whl → 12.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/METADATA +1 -1
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/RECORD +62 -60
- phoenix/auth.py +8 -2
- phoenix/db/models.py +3 -3
- phoenix/server/api/auth.py +9 -0
- phoenix/server/api/context.py +2 -0
- phoenix/server/api/dataloaders/__init__.py +2 -0
- phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/input_types/ProjectSessionSort.py +158 -1
- phoenix/server/api/input_types/SpanSort.py +2 -1
- phoenix/server/api/input_types/UserRoleInput.py +1 -0
- phoenix/server/api/mutations/annotation_config_mutations.py +6 -6
- phoenix/server/api/mutations/api_key_mutations.py +13 -5
- phoenix/server/api/mutations/chat_mutations.py +3 -3
- phoenix/server/api/mutations/dataset_label_mutations.py +6 -6
- phoenix/server/api/mutations/dataset_mutations.py +8 -8
- phoenix/server/api/mutations/dataset_split_mutations.py +7 -7
- phoenix/server/api/mutations/experiment_mutations.py +2 -2
- phoenix/server/api/mutations/export_events_mutations.py +3 -3
- phoenix/server/api/mutations/model_mutations.py +4 -4
- phoenix/server/api/mutations/project_mutations.py +4 -4
- phoenix/server/api/mutations/project_session_annotations_mutations.py +4 -4
- phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
- phoenix/server/api/mutations/prompt_label_mutations.py +7 -7
- phoenix/server/api/mutations/prompt_mutations.py +7 -7
- phoenix/server/api/mutations/prompt_version_tag_mutations.py +3 -3
- phoenix/server/api/mutations/span_annotations_mutations.py +5 -5
- phoenix/server/api/mutations/trace_annotations_mutations.py +4 -4
- phoenix/server/api/mutations/trace_mutations.py +3 -3
- phoenix/server/api/mutations/user_mutations.py +8 -5
- phoenix/server/api/routers/auth.py +2 -2
- phoenix/server/api/routers/v1/__init__.py +16 -1
- phoenix/server/api/routers/v1/annotation_configs.py +7 -1
- phoenix/server/api/routers/v1/datasets.py +48 -8
- phoenix/server/api/routers/v1/experiment_runs.py +7 -1
- phoenix/server/api/routers/v1/experiments.py +41 -5
- phoenix/server/api/routers/v1/projects.py +3 -31
- phoenix/server/api/routers/v1/users.py +0 -7
- phoenix/server/api/subscriptions.py +3 -3
- phoenix/server/api/types/Dataset.py +95 -6
- phoenix/server/api/types/Experiment.py +60 -25
- phoenix/server/api/types/Project.py +24 -68
- phoenix/server/app.py +2 -0
- phoenix/server/authorization.py +3 -1
- phoenix/server/bearer_auth.py +9 -0
- phoenix/server/jwt_store.py +8 -6
- phoenix/server/static/.vite/manifest.json +44 -44
- phoenix/server/static/assets/{components-BvsExS75.js → components-CboqzKQ9.js} +520 -397
- phoenix/server/static/assets/{index-iq8WDxat.js → index-CYYGI5-x.js} +2 -2
- phoenix/server/static/assets/{pages-Ckg4SLQ9.js → pages-DdlUeKi2.js} +616 -604
- phoenix/server/static/assets/vendor-CQ4tN9P7.js +918 -0
- phoenix/server/static/assets/vendor-arizeai-Cb1ncvYH.js +106 -0
- phoenix/server/static/assets/{vendor-codemirror-1bq_t1Ec.js → vendor-codemirror-CckmKopH.js} +3 -3
- phoenix/server/static/assets/{vendor-recharts-DQ4xfrf4.js → vendor-recharts-BC1ysIKu.js} +1 -1
- phoenix/server/static/assets/{vendor-shiki-GGmcIQxA.js → vendor-shiki-B45T-YxN.js} +1 -1
- phoenix/server/static/assets/vendor-three-BtCyLs1w.js +3840 -0
- phoenix/version.py +1 -1
- phoenix/server/static/assets/vendor-D2eEI-6h.js +0 -914
- phoenix/server/static/assets/vendor-arizeai-kfOei7nf.js +0 -156
- phoenix/server/static/assets/vendor-three-BLWp5bic.js +0 -2998
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -18,7 +18,7 @@ from strawberry.types import Info
|
|
|
18
18
|
|
|
19
19
|
from phoenix.db import models
|
|
20
20
|
from phoenix.db.helpers import get_eval_trace_ids_for_datasets, get_project_names_for_datasets
|
|
21
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
21
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
22
22
|
from phoenix.server.api.context import Context
|
|
23
23
|
from phoenix.server.api.exceptions import BadRequest, NotFound
|
|
24
24
|
from phoenix.server.api.helpers.dataset_helpers import (
|
|
@@ -50,7 +50,7 @@ class DatasetMutationPayload:
|
|
|
50
50
|
|
|
51
51
|
@strawberry.type
|
|
52
52
|
class DatasetMutationMixin:
|
|
53
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
53
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
54
54
|
async def create_dataset(
|
|
55
55
|
self,
|
|
56
56
|
info: Info[Context, None],
|
|
@@ -74,7 +74,7 @@ class DatasetMutationMixin:
|
|
|
74
74
|
info.context.event_queue.put(DatasetInsertEvent((dataset.id,)))
|
|
75
75
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
76
76
|
|
|
77
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
77
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
78
78
|
async def patch_dataset(
|
|
79
79
|
self,
|
|
80
80
|
info: Info[Context, None],
|
|
@@ -103,7 +103,7 @@ class DatasetMutationMixin:
|
|
|
103
103
|
info.context.event_queue.put(DatasetInsertEvent((dataset.id,)))
|
|
104
104
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
105
105
|
|
|
106
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
106
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
107
107
|
async def add_spans_to_dataset(
|
|
108
108
|
self,
|
|
109
109
|
info: Info[Context, None],
|
|
@@ -223,7 +223,7 @@ class DatasetMutationMixin:
|
|
|
223
223
|
info.context.event_queue.put(DatasetInsertEvent((dataset.id,)))
|
|
224
224
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
225
225
|
|
|
226
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
226
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
227
227
|
async def add_examples_to_dataset(
|
|
228
228
|
self, info: Info[Context, None], input: AddExamplesToDatasetInput
|
|
229
229
|
) -> DatasetMutationPayload:
|
|
@@ -350,7 +350,7 @@ class DatasetMutationMixin:
|
|
|
350
350
|
info.context.event_queue.put(DatasetInsertEvent((dataset.id,)))
|
|
351
351
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
352
352
|
|
|
353
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
353
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
354
354
|
async def delete_dataset(
|
|
355
355
|
self,
|
|
356
356
|
info: Info[Context, None],
|
|
@@ -381,7 +381,7 @@ class DatasetMutationMixin:
|
|
|
381
381
|
info.context.event_queue.put(DatasetDeleteEvent((dataset.id,)))
|
|
382
382
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
383
383
|
|
|
384
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
384
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
385
385
|
async def patch_dataset_examples(
|
|
386
386
|
self,
|
|
387
387
|
info: Info[Context, None],
|
|
@@ -474,7 +474,7 @@ class DatasetMutationMixin:
|
|
|
474
474
|
info.context.event_queue.put(DatasetInsertEvent((dataset.id,)))
|
|
475
475
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
476
476
|
|
|
477
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
477
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
478
478
|
async def delete_dataset_examples(
|
|
479
479
|
self, info: Info[Context, None], input: DeleteDatasetExamplesInput
|
|
480
480
|
) -> DatasetMutationPayload:
|
|
@@ -10,7 +10,7 @@ from strawberry.scalars import JSON
|
|
|
10
10
|
from strawberry.types import Info
|
|
11
11
|
|
|
12
12
|
from phoenix.db import models
|
|
13
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
13
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
14
14
|
from phoenix.server.api.context import Context
|
|
15
15
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
|
|
16
16
|
from phoenix.server.api.helpers.playground_users import get_user
|
|
@@ -96,7 +96,7 @@ class RemoveDatasetExamplesFromDatasetSplitsMutationPayload:
|
|
|
96
96
|
|
|
97
97
|
@strawberry.type
|
|
98
98
|
class DatasetSplitMutationMixin:
|
|
99
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
99
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
100
100
|
async def create_dataset_split(
|
|
101
101
|
self, info: Info[Context, None], input: CreateDatasetSplitInput
|
|
102
102
|
) -> DatasetSplitMutationPayload:
|
|
@@ -119,7 +119,7 @@ class DatasetSplitMutationMixin:
|
|
|
119
119
|
dataset_split=to_gql_dataset_split(dataset_split_orm), query=Query()
|
|
120
120
|
)
|
|
121
121
|
|
|
122
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
122
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
123
123
|
async def patch_dataset_split(
|
|
124
124
|
self, info: Info[Context, None], input: PatchDatasetSplitInput
|
|
125
125
|
) -> DatasetSplitMutationPayload:
|
|
@@ -152,7 +152,7 @@ class DatasetSplitMutationMixin:
|
|
|
152
152
|
query=Query(),
|
|
153
153
|
)
|
|
154
154
|
|
|
155
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
155
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
156
156
|
async def delete_dataset_splits(
|
|
157
157
|
self, info: Info[Context, None], input: DeleteDatasetSplitInput
|
|
158
158
|
) -> DeleteDatasetSplitsMutationPayload:
|
|
@@ -191,7 +191,7 @@ class DatasetSplitMutationMixin:
|
|
|
191
191
|
query=Query(),
|
|
192
192
|
)
|
|
193
193
|
|
|
194
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
194
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
195
195
|
async def add_dataset_examples_to_dataset_splits(
|
|
196
196
|
self, info: Info[Context, None], input: AddDatasetExamplesToDatasetSplitsInput
|
|
197
197
|
) -> AddDatasetExamplesToDatasetSplitsMutationPayload:
|
|
@@ -284,7 +284,7 @@ class DatasetSplitMutationMixin:
|
|
|
284
284
|
examples=[to_gql_dataset_example(example) for example in examples],
|
|
285
285
|
)
|
|
286
286
|
|
|
287
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
287
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
288
288
|
async def remove_dataset_examples_from_dataset_splits(
|
|
289
289
|
self, info: Info[Context, None], input: RemoveDatasetExamplesFromDatasetSplitsInput
|
|
290
290
|
) -> RemoveDatasetExamplesFromDatasetSplitsMutationPayload:
|
|
@@ -345,7 +345,7 @@ class DatasetSplitMutationMixin:
|
|
|
345
345
|
examples=[to_gql_dataset_example(example) for example in examples],
|
|
346
346
|
)
|
|
347
347
|
|
|
348
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
348
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
349
349
|
async def create_dataset_split_with_examples(
|
|
350
350
|
self, info: Info[Context, None], input: CreateDatasetSplitWithExamplesInput
|
|
351
351
|
) -> DatasetSplitMutationPayloadWithExamples:
|
|
@@ -7,7 +7,7 @@ from strawberry.types import Info
|
|
|
7
7
|
|
|
8
8
|
from phoenix.db import models
|
|
9
9
|
from phoenix.db.helpers import get_eval_trace_ids_for_experiments, get_project_names_for_experiments
|
|
10
|
-
from phoenix.server.api.auth import IsNotReadOnly
|
|
10
|
+
from phoenix.server.api.auth import IsNotReadOnly, IsNotViewer
|
|
11
11
|
from phoenix.server.api.context import Context
|
|
12
12
|
from phoenix.server.api.exceptions import CustomGraphQLError
|
|
13
13
|
from phoenix.server.api.input_types.DeleteExperimentsInput import DeleteExperimentsInput
|
|
@@ -24,7 +24,7 @@ class ExperimentMutationPayload:
|
|
|
24
24
|
|
|
25
25
|
@strawberry.type
|
|
26
26
|
class ExperimentMutationMixin:
|
|
27
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
27
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
28
28
|
async def delete_experiments(
|
|
29
29
|
self,
|
|
30
30
|
info: Info[Context, None],
|
|
@@ -8,7 +8,7 @@ from strawberry import ID, UNSET
|
|
|
8
8
|
from strawberry.types import Info
|
|
9
9
|
|
|
10
10
|
import phoenix.core.model_schema as ms
|
|
11
|
-
from phoenix.server.api.auth import IsNotReadOnly
|
|
11
|
+
from phoenix.server.api.auth import IsNotReadOnly, IsNotViewer
|
|
12
12
|
from phoenix.server.api.context import Context
|
|
13
13
|
from phoenix.server.api.input_types.ClusterInput import ClusterInput
|
|
14
14
|
from phoenix.server.api.types.Event import parse_event_ids_by_inferences_role, unpack_event_id
|
|
@@ -19,7 +19,7 @@ from phoenix.server.api.types.InferencesRole import AncillaryInferencesRole, Inf
|
|
|
19
19
|
@strawberry.type
|
|
20
20
|
class ExportEventsMutationMixin:
|
|
21
21
|
@strawberry.mutation(
|
|
22
|
-
permission_classes=[IsNotReadOnly],
|
|
22
|
+
permission_classes=[IsNotReadOnly, IsNotViewer],
|
|
23
23
|
description=(
|
|
24
24
|
"Given a list of event ids, export the corresponding data subset in Parquet format."
|
|
25
25
|
" File name is optional, but if specified, should be without file extension. By default"
|
|
@@ -51,7 +51,7 @@ class ExportEventsMutationMixin:
|
|
|
51
51
|
return ExportedFile(file_name=file_name)
|
|
52
52
|
|
|
53
53
|
@strawberry.mutation(
|
|
54
|
-
permission_classes=[IsNotReadOnly],
|
|
54
|
+
permission_classes=[IsNotReadOnly, IsNotViewer],
|
|
55
55
|
description=(
|
|
56
56
|
"Given a list of clusters, export the corresponding data subset in Parquet format."
|
|
57
57
|
" File name is optional, but if specified, should be without file extension. By default"
|
|
@@ -12,7 +12,7 @@ from strawberry.relay import GlobalID
|
|
|
12
12
|
from strawberry.types import Info
|
|
13
13
|
|
|
14
14
|
from phoenix.db import models
|
|
15
|
-
from phoenix.server.api.auth import IsNotReadOnly
|
|
15
|
+
from phoenix.server.api.auth import IsNotReadOnly, IsNotViewer
|
|
16
16
|
from phoenix.server.api.context import Context
|
|
17
17
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
|
|
18
18
|
from phoenix.server.api.queries import Query
|
|
@@ -81,7 +81,7 @@ class DeleteModelMutationPayload:
|
|
|
81
81
|
|
|
82
82
|
@strawberry.type
|
|
83
83
|
class ModelMutationMixin:
|
|
84
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
84
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
85
85
|
async def create_model(
|
|
86
86
|
self,
|
|
87
87
|
info: Info[Context, None],
|
|
@@ -114,7 +114,7 @@ class ModelMutationMixin:
|
|
|
114
114
|
query=Query(),
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
117
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
118
118
|
async def update_model(
|
|
119
119
|
self,
|
|
120
120
|
info: Info[Context, None],
|
|
@@ -167,7 +167,7 @@ class ModelMutationMixin:
|
|
|
167
167
|
query=Query(),
|
|
168
168
|
)
|
|
169
169
|
|
|
170
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
170
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
171
171
|
async def delete_model(
|
|
172
172
|
self,
|
|
173
173
|
info: Info[Context, None],
|
|
@@ -8,7 +8,7 @@ from strawberry.types import Info
|
|
|
8
8
|
|
|
9
9
|
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
10
10
|
from phoenix.db import models
|
|
11
|
-
from phoenix.server.api.auth import IsNotReadOnly
|
|
11
|
+
from phoenix.server.api.auth import IsNotReadOnly, IsNotViewer
|
|
12
12
|
from phoenix.server.api.context import Context
|
|
13
13
|
from phoenix.server.api.exceptions import BadRequest, Conflict
|
|
14
14
|
from phoenix.server.api.input_types.ClearProjectInput import ClearProjectInput
|
|
@@ -27,7 +27,7 @@ class ProjectMutationPayload:
|
|
|
27
27
|
|
|
28
28
|
@strawberry.type
|
|
29
29
|
class ProjectMutationMixin:
|
|
30
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
30
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
31
31
|
async def create_project(
|
|
32
32
|
self,
|
|
33
33
|
info: Info[Context, None],
|
|
@@ -52,7 +52,7 @@ class ProjectMutationMixin:
|
|
|
52
52
|
info.context.event_queue.put(ProjectInsertEvent((project.id,)))
|
|
53
53
|
return ProjectMutationPayload(project=to_gql_project(project), query=Query())
|
|
54
54
|
|
|
55
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
55
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
56
56
|
async def delete_project(self, info: Info[Context, None], id: GlobalID) -> Query:
|
|
57
57
|
project_id = from_global_id_with_expected_type(global_id=id, expected_type_name="Project")
|
|
58
58
|
async with info.context.db() as session:
|
|
@@ -69,7 +69,7 @@ class ProjectMutationMixin:
|
|
|
69
69
|
info.context.event_queue.put(ProjectDeleteEvent((project_id,)))
|
|
70
70
|
return Query()
|
|
71
71
|
|
|
72
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
72
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
73
73
|
async def clear_project(self, info: Info[Context, None], input: ClearProjectInput) -> Query:
|
|
74
74
|
project_id = from_global_id_with_expected_type(
|
|
75
75
|
global_id=input.id, expected_type_name="Project"
|
|
@@ -8,7 +8,7 @@ from strawberry import Info
|
|
|
8
8
|
from strawberry.relay import GlobalID
|
|
9
9
|
|
|
10
10
|
from phoenix.db import models
|
|
11
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
11
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
12
12
|
from phoenix.server.api.context import Context
|
|
13
13
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound, Unauthorized
|
|
14
14
|
from phoenix.server.api.helpers.annotations import get_user_identifier
|
|
@@ -38,7 +38,7 @@ class ProjectSessionAnnotationMutationPayload:
|
|
|
38
38
|
|
|
39
39
|
@strawberry.type
|
|
40
40
|
class ProjectSessionAnnotationMutationMixin:
|
|
41
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
41
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
42
42
|
async def create_project_session_annotations(
|
|
43
43
|
self, info: Info[Context, None], input: CreateProjectSessionAnnotationInput
|
|
44
44
|
) -> ProjectSessionAnnotationMutationPayload:
|
|
@@ -85,7 +85,7 @@ class ProjectSessionAnnotationMutationMixin:
|
|
|
85
85
|
query=Query(),
|
|
86
86
|
)
|
|
87
87
|
|
|
88
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
88
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
89
89
|
async def update_project_session_annotations(
|
|
90
90
|
self, info: Info[Context, None], input: UpdateAnnotationInput
|
|
91
91
|
) -> ProjectSessionAnnotationMutationPayload:
|
|
@@ -126,7 +126,7 @@ class ProjectSessionAnnotationMutationMixin:
|
|
|
126
126
|
query=Query(),
|
|
127
127
|
)
|
|
128
128
|
|
|
129
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
129
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
130
130
|
async def delete_project_session_annotation(
|
|
131
131
|
self, info: Info[Context, None], id: GlobalID
|
|
132
132
|
) -> ProjectSessionAnnotationMutationPayload:
|
|
@@ -16,7 +16,7 @@ from phoenix.db.types.trace_retention import (
|
|
|
16
16
|
TraceRetentionCronExpression,
|
|
17
17
|
TraceRetentionRule,
|
|
18
18
|
)
|
|
19
|
-
from phoenix.server.api.auth import IsAdminIfAuthEnabled, IsLocked, IsNotReadOnly
|
|
19
|
+
from phoenix.server.api.auth import IsAdminIfAuthEnabled, IsLocked, IsNotReadOnly, IsNotViewer
|
|
20
20
|
from phoenix.server.api.context import Context
|
|
21
21
|
from phoenix.server.api.exceptions import BadRequest, NotFound
|
|
22
22
|
from phoenix.server.api.queries import Query
|
|
@@ -113,7 +113,9 @@ class ProjectTraceRetentionPolicyMutationPayload:
|
|
|
113
113
|
|
|
114
114
|
@strawberry.type
|
|
115
115
|
class ProjectTraceRetentionPolicyMutationMixin:
|
|
116
|
-
@strawberry.mutation(
|
|
116
|
+
@strawberry.mutation(
|
|
117
|
+
permission_classes=[IsNotReadOnly, IsNotViewer, IsAdminIfAuthEnabled, IsLocked]
|
|
118
|
+
) # type: ignore
|
|
117
119
|
async def create_project_trace_retention_policy(
|
|
118
120
|
self,
|
|
119
121
|
info: Info[Context, None],
|
|
@@ -146,7 +148,9 @@ class ProjectTraceRetentionPolicyMutationMixin:
|
|
|
146
148
|
node=ProjectTraceRetentionPolicy(id=policy.id, db_policy=policy),
|
|
147
149
|
)
|
|
148
150
|
|
|
149
|
-
@strawberry.mutation(
|
|
151
|
+
@strawberry.mutation(
|
|
152
|
+
permission_classes=[IsNotReadOnly, IsNotViewer, IsAdminIfAuthEnabled, IsLocked]
|
|
153
|
+
) # type: ignore
|
|
150
154
|
async def patch_project_trace_retention_policy(
|
|
151
155
|
self,
|
|
152
156
|
info: Info[Context, None],
|
|
@@ -204,7 +208,7 @@ class ProjectTraceRetentionPolicyMutationMixin:
|
|
|
204
208
|
node=ProjectTraceRetentionPolicy(id=policy.id, db_policy=policy),
|
|
205
209
|
)
|
|
206
210
|
|
|
207
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsAdminIfAuthEnabled]) # type: ignore
|
|
211
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsAdminIfAuthEnabled]) # type: ignore
|
|
208
212
|
async def delete_project_trace_retention_policy(
|
|
209
213
|
self,
|
|
210
214
|
info: Info[Context, None],
|
|
@@ -10,7 +10,7 @@ from strawberry.relay import GlobalID
|
|
|
10
10
|
from strawberry.types import Info
|
|
11
11
|
|
|
12
12
|
from phoenix.db import models
|
|
13
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
13
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
14
14
|
from phoenix.server.api.context import Context
|
|
15
15
|
from phoenix.server.api.exceptions import Conflict, NotFound
|
|
16
16
|
from phoenix.server.api.queries import Query
|
|
@@ -69,7 +69,7 @@ class PromptLabelAssociationMutationPayload:
|
|
|
69
69
|
|
|
70
70
|
@strawberry.type
|
|
71
71
|
class PromptLabelMutationMixin:
|
|
72
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
72
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
73
73
|
async def create_prompt_label(
|
|
74
74
|
self, info: Info[Context, None], input: CreatePromptLabelInput
|
|
75
75
|
) -> PromptLabelMutationPayload:
|
|
@@ -89,7 +89,7 @@ class PromptLabelMutationMixin:
|
|
|
89
89
|
query=Query(),
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
92
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
93
93
|
async def patch_prompt_label(
|
|
94
94
|
self, info: Info[Context, None], input: PatchPromptLabelInput
|
|
95
95
|
) -> PromptLabelMutationPayload:
|
|
@@ -117,7 +117,7 @@ class PromptLabelMutationMixin:
|
|
|
117
117
|
query=Query(),
|
|
118
118
|
)
|
|
119
119
|
|
|
120
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
120
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
121
121
|
async def delete_prompt_labels(
|
|
122
122
|
self, info: Info[Context, None], input: DeletePromptLabelsInput
|
|
123
123
|
) -> PromptLabelDeleteMutationPayload:
|
|
@@ -139,7 +139,7 @@ class PromptLabelMutationMixin:
|
|
|
139
139
|
query=Query(),
|
|
140
140
|
)
|
|
141
141
|
|
|
142
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
142
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
143
143
|
async def set_prompt_labels(
|
|
144
144
|
self, info: Info[Context, None], input: SetPromptLabelsInput
|
|
145
145
|
) -> PromptLabelAssociationMutationPayload:
|
|
@@ -168,7 +168,7 @@ class PromptLabelMutationMixin:
|
|
|
168
168
|
query=Query(),
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
171
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
172
172
|
async def unset_prompt_labels(
|
|
173
173
|
self, info: Info[Context, None], input: UnsetPromptLabelsInput
|
|
174
174
|
) -> PromptLabelAssociationMutationPayload:
|
|
@@ -188,7 +188,7 @@ class PromptLabelMutationMixin:
|
|
|
188
188
|
)
|
|
189
189
|
result = await session.execute(stmt)
|
|
190
190
|
|
|
191
|
-
if result.rowcount != len(label_ids):
|
|
191
|
+
if result.rowcount != len(label_ids): # type: ignore[attr-defined]
|
|
192
192
|
label_ids_str = ", ".join(str(i) for i in label_ids)
|
|
193
193
|
raise NotFound(
|
|
194
194
|
f"No association between prompt={prompt_id} and labels={label_ids_str}."
|
|
@@ -13,7 +13,7 @@ from strawberry.types import Info
|
|
|
13
13
|
from phoenix.db import models
|
|
14
14
|
from phoenix.db.types.identifier import Identifier as IdentifierModel
|
|
15
15
|
from phoenix.db.types.model_provider import ModelProvider
|
|
16
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
16
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
17
17
|
from phoenix.server.api.context import Context
|
|
18
18
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
|
|
19
19
|
from phoenix.server.api.helpers.prompts.models import (
|
|
@@ -75,7 +75,7 @@ class DeletePromptMutationPayload:
|
|
|
75
75
|
|
|
76
76
|
@strawberry.type
|
|
77
77
|
class PromptMutationMixin:
|
|
78
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
78
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
79
79
|
async def create_chat_prompt(
|
|
80
80
|
self, info: Info[Context, None], input: CreateChatPromptInput
|
|
81
81
|
) -> Prompt:
|
|
@@ -142,7 +142,7 @@ class PromptMutationMixin:
|
|
|
142
142
|
raise Conflict(f"A prompt named '{input.name}' already exists")
|
|
143
143
|
return to_gql_prompt_from_orm(prompt)
|
|
144
144
|
|
|
145
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
145
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
146
146
|
async def create_chat_prompt_version(
|
|
147
147
|
self,
|
|
148
148
|
info: Info[Context, None],
|
|
@@ -220,7 +220,7 @@ class PromptMutationMixin:
|
|
|
220
220
|
|
|
221
221
|
return to_gql_prompt_from_orm(prompt)
|
|
222
222
|
|
|
223
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
223
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
224
224
|
async def delete_prompt(
|
|
225
225
|
self, info: Info[Context, None], input: DeletePromptInput
|
|
226
226
|
) -> DeletePromptMutationPayload:
|
|
@@ -231,13 +231,13 @@ class PromptMutationMixin:
|
|
|
231
231
|
stmt = delete(models.Prompt).where(models.Prompt.id == prompt_id)
|
|
232
232
|
result = await session.execute(stmt)
|
|
233
233
|
|
|
234
|
-
if result.rowcount == 0:
|
|
234
|
+
if result.rowcount == 0: # type: ignore[attr-defined]
|
|
235
235
|
raise NotFound(f"Prompt with ID '{input.prompt_id}' not found")
|
|
236
236
|
|
|
237
237
|
await session.commit()
|
|
238
238
|
return DeletePromptMutationPayload(query=Query())
|
|
239
239
|
|
|
240
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
240
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
241
241
|
async def clone_prompt(self, info: Info[Context, None], input: ClonePromptInput) -> Prompt:
|
|
242
242
|
prompt_id = from_global_id_with_expected_type(
|
|
243
243
|
global_id=input.prompt_id, expected_type_name=Prompt.__name__
|
|
@@ -290,7 +290,7 @@ class PromptMutationMixin:
|
|
|
290
290
|
raise Conflict(f"A prompt named '{input.name}' already exists")
|
|
291
291
|
return to_gql_prompt_from_orm(new_prompt)
|
|
292
292
|
|
|
293
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
293
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
294
294
|
async def patch_prompt(self, info: Info[Context, None], input: PatchPromptInput) -> Prompt:
|
|
295
295
|
prompt_id = from_global_id_with_expected_type(
|
|
296
296
|
global_id=input.prompt_id, expected_type_name=Prompt.__name__
|
|
@@ -10,7 +10,7 @@ from strawberry.types import Info
|
|
|
10
10
|
|
|
11
11
|
from phoenix.db import models
|
|
12
12
|
from phoenix.db.types.identifier import Identifier as IdentifierModel
|
|
13
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
13
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
14
14
|
from phoenix.server.api.context import Context
|
|
15
15
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
|
|
16
16
|
from phoenix.server.api.queries import Query
|
|
@@ -42,7 +42,7 @@ class PromptVersionTagMutationPayload:
|
|
|
42
42
|
|
|
43
43
|
@strawberry.type
|
|
44
44
|
class PromptVersionTagMutationMixin:
|
|
45
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
45
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
46
46
|
async def delete_prompt_version_tag(
|
|
47
47
|
self, info: Info[Context, None], input: DeletePromptVersionTagInput
|
|
48
48
|
) -> PromptVersionTagMutationPayload:
|
|
@@ -78,7 +78,7 @@ class PromptVersionTagMutationMixin:
|
|
|
78
78
|
prompt_version_tag=None, query=Query(), prompt=to_gql_prompt_from_orm(prompt)
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
81
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
82
82
|
async def set_prompt_version_tag(
|
|
83
83
|
self, info: Info[Context, None], input: SetPromptVersionTagInput
|
|
84
84
|
) -> PromptVersionTagMutationPayload:
|
|
@@ -7,7 +7,7 @@ from starlette.requests import Request
|
|
|
7
7
|
from strawberry import UNSET, Info
|
|
8
8
|
|
|
9
9
|
from phoenix.db import models
|
|
10
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
10
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
11
11
|
from phoenix.server.api.context import Context
|
|
12
12
|
from phoenix.server.api.exceptions import BadRequest, NotFound, Unauthorized
|
|
13
13
|
from phoenix.server.api.helpers.annotations import get_user_identifier
|
|
@@ -34,7 +34,7 @@ class SpanAnnotationMutationPayload:
|
|
|
34
34
|
|
|
35
35
|
@strawberry.type
|
|
36
36
|
class SpanAnnotationMutationMixin:
|
|
37
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
37
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
38
38
|
async def create_span_annotations(
|
|
39
39
|
self, info: Info[Context, None], input: list[CreateSpanAnnotationInput]
|
|
40
40
|
) -> SpanAnnotationMutationPayload:
|
|
@@ -148,7 +148,7 @@ class SpanAnnotationMutationMixin:
|
|
|
148
148
|
query=Query(),
|
|
149
149
|
)
|
|
150
150
|
|
|
151
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
151
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
152
152
|
async def create_span_note(
|
|
153
153
|
self, info: Info[Context, None], annotation_input: CreateSpanNoteInput
|
|
154
154
|
) -> SpanAnnotationMutationPayload:
|
|
@@ -191,7 +191,7 @@ class SpanAnnotationMutationMixin:
|
|
|
191
191
|
query=Query(),
|
|
192
192
|
)
|
|
193
193
|
|
|
194
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
194
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
195
195
|
async def patch_span_annotations(
|
|
196
196
|
self, info: Info[Context, None], input: list[PatchAnnotationInput]
|
|
197
197
|
) -> SpanAnnotationMutationPayload:
|
|
@@ -268,7 +268,7 @@ class SpanAnnotationMutationMixin:
|
|
|
268
268
|
query=Query(),
|
|
269
269
|
)
|
|
270
270
|
|
|
271
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
271
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
272
272
|
async def delete_span_annotations(
|
|
273
273
|
self, info: Info[Context, None], input: DeleteAnnotationsInput
|
|
274
274
|
) -> SpanAnnotationMutationPayload:
|
|
@@ -6,7 +6,7 @@ from starlette.requests import Request
|
|
|
6
6
|
from strawberry import UNSET, Info
|
|
7
7
|
|
|
8
8
|
from phoenix.db import models
|
|
9
|
-
from phoenix.server.api.auth import IsLocked, IsNotReadOnly
|
|
9
|
+
from phoenix.server.api.auth import IsLocked, IsNotReadOnly, IsNotViewer
|
|
10
10
|
from phoenix.server.api.context import Context
|
|
11
11
|
from phoenix.server.api.exceptions import BadRequest, NotFound, Unauthorized
|
|
12
12
|
from phoenix.server.api.helpers.annotations import get_user_identifier
|
|
@@ -29,7 +29,7 @@ class TraceAnnotationMutationPayload:
|
|
|
29
29
|
|
|
30
30
|
@strawberry.type
|
|
31
31
|
class TraceAnnotationMutationMixin:
|
|
32
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
32
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
33
33
|
async def create_trace_annotations(
|
|
34
34
|
self, info: Info[Context, None], input: list[CreateTraceAnnotationInput]
|
|
35
35
|
) -> TraceAnnotationMutationPayload:
|
|
@@ -120,7 +120,7 @@ class TraceAnnotationMutationMixin:
|
|
|
120
120
|
query=Query(),
|
|
121
121
|
)
|
|
122
122
|
|
|
123
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
|
|
123
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsLocked]) # type: ignore
|
|
124
124
|
async def patch_trace_annotations(
|
|
125
125
|
self, info: Info[Context, None], input: list[PatchAnnotationInput]
|
|
126
126
|
) -> TraceAnnotationMutationPayload:
|
|
@@ -195,7 +195,7 @@ class TraceAnnotationMutationMixin:
|
|
|
195
195
|
query=Query(),
|
|
196
196
|
)
|
|
197
197
|
|
|
198
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
198
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
199
199
|
async def delete_trace_annotations(
|
|
200
200
|
self, info: Info[Context, None], input: DeleteAnnotationsInput
|
|
201
201
|
) -> TraceAnnotationMutationPayload:
|
|
@@ -6,7 +6,7 @@ from strawberry.relay import GlobalID
|
|
|
6
6
|
from strawberry.types import Info
|
|
7
7
|
|
|
8
8
|
from phoenix.db import models
|
|
9
|
-
from phoenix.server.api.auth import IsNotReadOnly
|
|
9
|
+
from phoenix.server.api.auth import IsNotReadOnly, IsNotViewer
|
|
10
10
|
from phoenix.server.api.context import Context
|
|
11
11
|
from phoenix.server.api.exceptions import BadRequest
|
|
12
12
|
from phoenix.server.api.queries import Query
|
|
@@ -16,7 +16,7 @@ from phoenix.server.dml_event import SpanDeleteEvent
|
|
|
16
16
|
|
|
17
17
|
@strawberry.type
|
|
18
18
|
class TraceMutationMixin:
|
|
19
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
19
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
20
20
|
async def delete_traces(
|
|
21
21
|
self,
|
|
22
22
|
info: Info[Context, None],
|
|
@@ -73,7 +73,7 @@ class TraceMutationMixin:
|
|
|
73
73
|
info.context.event_queue.put(SpanDeleteEvent(project_ids))
|
|
74
74
|
return Query()
|
|
75
75
|
|
|
76
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
|
|
76
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer]) # type: ignore
|
|
77
77
|
async def transfer_traces_to_project(
|
|
78
78
|
self,
|
|
79
79
|
info: Info[Context, None],
|
|
@@ -27,7 +27,7 @@ from phoenix.auth import (
|
|
|
27
27
|
)
|
|
28
28
|
from phoenix.config import get_env_disable_basic_auth
|
|
29
29
|
from phoenix.db import models
|
|
30
|
-
from phoenix.server.api.auth import IsAdmin, IsLocked, IsNotReadOnly
|
|
30
|
+
from phoenix.server.api.auth import IsAdmin, IsLocked, IsNotReadOnly, IsNotViewer
|
|
31
31
|
from phoenix.server.api.context import Context
|
|
32
32
|
from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound, Unauthorized
|
|
33
33
|
from phoenix.server.api.input_types.UserRoleInput import UserRoleInput
|
|
@@ -110,7 +110,7 @@ class UserMutationPayload:
|
|
|
110
110
|
|
|
111
111
|
@strawberry.type
|
|
112
112
|
class UserMutationMixin:
|
|
113
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsAdmin, IsLocked]) # type: ignore
|
|
113
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsAdmin, IsLocked]) # type: ignore
|
|
114
114
|
async def create_user(
|
|
115
115
|
self,
|
|
116
116
|
info: Info[Context, None],
|
|
@@ -157,7 +157,7 @@ class UserMutationMixin:
|
|
|
157
157
|
logger.error(f"Failed to send welcome email: {error}")
|
|
158
158
|
return UserMutationPayload(user=to_gql_user(user))
|
|
159
159
|
|
|
160
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsAdmin]) # type: ignore
|
|
160
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsAdmin]) # type: ignore
|
|
161
161
|
async def patch_user(
|
|
162
162
|
self,
|
|
163
163
|
info: Info[Context, None],
|
|
@@ -174,6 +174,7 @@ class UserMutationMixin:
|
|
|
174
174
|
if not (user := await session.scalar(_select_user_by_id(user_id))):
|
|
175
175
|
raise NotFound("User not found")
|
|
176
176
|
stack.enter_context(session.no_autoflush)
|
|
177
|
+
should_log_out = False
|
|
177
178
|
if input.new_role:
|
|
178
179
|
if user.email == DEFAULT_ADMIN_EMAIL:
|
|
179
180
|
raise Unauthorized("Cannot modify role for the default admin user")
|
|
@@ -183,6 +184,7 @@ class UserMutationMixin:
|
|
|
183
184
|
if user_role_id is None:
|
|
184
185
|
raise NotFound(f"Role {input.new_role.value} not found")
|
|
185
186
|
user.user_role_id = user_role_id
|
|
187
|
+
should_log_out = True
|
|
186
188
|
if password := input.new_password:
|
|
187
189
|
if user.auth_method != "LOCAL":
|
|
188
190
|
raise Conflict("Cannot modify password for non-local user")
|
|
@@ -191,6 +193,7 @@ class UserMutationMixin:
|
|
|
191
193
|
user.password_salt = salt
|
|
192
194
|
user.password_hash = await info.context.hash_password(Secret(password), salt)
|
|
193
195
|
user.reset_password = True
|
|
196
|
+
should_log_out = True
|
|
194
197
|
if username := input.new_username:
|
|
195
198
|
user.username = username
|
|
196
199
|
assert user in session.dirty
|
|
@@ -199,7 +202,7 @@ class UserMutationMixin:
|
|
|
199
202
|
except (PostgreSQLIntegrityError, SQLiteIntegrityError) as error:
|
|
200
203
|
raise Conflict(_user_operation_error_message(error, "modify"))
|
|
201
204
|
assert user
|
|
202
|
-
if
|
|
205
|
+
if should_log_out:
|
|
203
206
|
await info.context.log_out(user.id)
|
|
204
207
|
return UserMutationPayload(user=to_gql_user(user))
|
|
205
208
|
|
|
@@ -245,7 +248,7 @@ class UserMutationMixin:
|
|
|
245
248
|
response.delete_cookie(PHOENIX_ACCESS_TOKEN_COOKIE_NAME)
|
|
246
249
|
return UserMutationPayload(user=to_gql_user(user))
|
|
247
250
|
|
|
248
|
-
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsAdmin, IsLocked]) # type: ignore
|
|
251
|
+
@strawberry.mutation(permission_classes=[IsNotReadOnly, IsNotViewer, IsAdmin, IsLocked]) # type: ignore
|
|
249
252
|
async def delete_users(
|
|
250
253
|
self,
|
|
251
254
|
info: Info[Context, None],
|