arize-phoenix 4.14.1__py3-none-any.whl → 4.16.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-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/METADATA +5 -3
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/RECORD +81 -71
- phoenix/db/bulk_inserter.py +131 -5
- phoenix/db/engines.py +2 -1
- phoenix/db/helpers.py +23 -1
- phoenix/db/insertion/constants.py +2 -0
- phoenix/db/insertion/document_annotation.py +157 -0
- phoenix/db/insertion/helpers.py +13 -0
- phoenix/db/insertion/span_annotation.py +144 -0
- phoenix/db/insertion/trace_annotation.py +144 -0
- phoenix/db/insertion/types.py +261 -0
- phoenix/experiments/functions.py +3 -2
- phoenix/experiments/types.py +3 -3
- phoenix/server/api/context.py +7 -9
- phoenix/server/api/dataloaders/__init__.py +2 -0
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +3 -3
- phoenix/server/api/dataloaders/dataset_example_revisions.py +2 -4
- phoenix/server/api/dataloaders/dataset_example_spans.py +2 -4
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -4
- phoenix/server/api/dataloaders/document_evaluations.py +2 -4
- phoenix/server/api/dataloaders/document_retrieval_metrics.py +2 -4
- phoenix/server/api/dataloaders/evaluation_summaries.py +2 -4
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +2 -4
- phoenix/server/api/dataloaders/experiment_error_rates.py +2 -4
- phoenix/server/api/dataloaders/experiment_run_counts.py +2 -4
- phoenix/server/api/dataloaders/experiment_sequence_number.py +2 -4
- phoenix/server/api/dataloaders/latency_ms_quantile.py +2 -3
- phoenix/server/api/dataloaders/min_start_or_max_end_times.py +2 -4
- phoenix/server/api/dataloaders/project_by_name.py +3 -3
- phoenix/server/api/dataloaders/record_counts.py +2 -4
- phoenix/server/api/dataloaders/span_annotations.py +2 -4
- phoenix/server/api/dataloaders/span_dataset_examples.py +36 -0
- phoenix/server/api/dataloaders/span_descendants.py +2 -4
- phoenix/server/api/dataloaders/span_evaluations.py +2 -4
- phoenix/server/api/dataloaders/span_projects.py +3 -3
- phoenix/server/api/dataloaders/token_counts.py +2 -4
- phoenix/server/api/dataloaders/trace_evaluations.py +2 -4
- phoenix/server/api/dataloaders/trace_row_ids.py +2 -4
- phoenix/server/api/input_types/SpanAnnotationSort.py +17 -0
- phoenix/server/api/input_types/TraceAnnotationSort.py +17 -0
- phoenix/server/api/mutations/span_annotations_mutations.py +8 -3
- phoenix/server/api/mutations/trace_annotations_mutations.py +8 -3
- phoenix/server/api/openapi/main.py +18 -2
- phoenix/server/api/openapi/schema.py +12 -12
- phoenix/server/api/routers/v1/__init__.py +36 -83
- phoenix/server/api/routers/v1/datasets.py +515 -509
- phoenix/server/api/routers/v1/evaluations.py +164 -73
- phoenix/server/api/routers/v1/experiment_evaluations.py +68 -91
- phoenix/server/api/routers/v1/experiment_runs.py +98 -155
- phoenix/server/api/routers/v1/experiments.py +132 -181
- phoenix/server/api/routers/v1/pydantic_compat.py +78 -0
- phoenix/server/api/routers/v1/spans.py +164 -203
- phoenix/server/api/routers/v1/traces.py +134 -159
- phoenix/server/api/routers/v1/utils.py +95 -0
- phoenix/server/api/types/Span.py +27 -3
- phoenix/server/api/types/Trace.py +21 -4
- phoenix/server/api/utils.py +4 -4
- phoenix/server/app.py +172 -192
- phoenix/server/grpc_server.py +2 -2
- phoenix/server/main.py +5 -9
- phoenix/server/static/.vite/manifest.json +31 -31
- phoenix/server/static/assets/components-Ci5kMOk5.js +1175 -0
- phoenix/server/static/assets/{index-CQgXRwU0.js → index-BQG5WVX7.js} +2 -2
- phoenix/server/static/assets/{pages-hdjlFZhO.js → pages-BrevprVW.js} +451 -275
- phoenix/server/static/assets/{vendor-DPvSDRn3.js → vendor-CP0b0YG0.js} +2 -2
- phoenix/server/static/assets/{vendor-arizeai-CkvPT67c.js → vendor-arizeai-DTbiPGp6.js} +27 -27
- phoenix/server/static/assets/vendor-codemirror-DtdPDzrv.js +15 -0
- phoenix/server/static/assets/{vendor-recharts-5jlNaZuF.js → vendor-recharts-A0DA1O99.js} +1 -1
- phoenix/server/thread_server.py +2 -2
- phoenix/server/types.py +18 -0
- phoenix/session/client.py +5 -3
- phoenix/session/session.py +2 -2
- phoenix/trace/dsl/filter.py +2 -6
- phoenix/trace/fixtures.py +17 -23
- phoenix/trace/utils.py +23 -0
- phoenix/utilities/client.py +116 -0
- phoenix/utilities/project.py +1 -1
- phoenix/version.py +1 -1
- phoenix/server/api/routers/v1/dataset_examples.py +0 -178
- phoenix/server/openapi/docs.py +0 -221
- phoenix/server/static/assets/components-DeS0YEmv.js +0 -1142
- phoenix/server/static/assets/vendor-codemirror-Cqwpwlua.js +0 -12
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
from sqlalchemy import and_, func, select
|
|
2
|
-
from starlette.requests import Request
|
|
3
|
-
from starlette.responses import JSONResponse, Response
|
|
4
|
-
from starlette.status import HTTP_404_NOT_FOUND
|
|
5
|
-
from strawberry.relay import GlobalID
|
|
6
|
-
|
|
7
|
-
from phoenix.db.models import Dataset, DatasetExample, DatasetExampleRevision, DatasetVersion
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
async def list_dataset_examples(request: Request) -> Response:
|
|
11
|
-
"""
|
|
12
|
-
summary: Get dataset examples by dataset ID
|
|
13
|
-
operationId: getDatasetExamples
|
|
14
|
-
tags:
|
|
15
|
-
- datasets
|
|
16
|
-
parameters:
|
|
17
|
-
- in: path
|
|
18
|
-
name: id
|
|
19
|
-
required: true
|
|
20
|
-
schema:
|
|
21
|
-
type: string
|
|
22
|
-
description: Dataset ID
|
|
23
|
-
- in: query
|
|
24
|
-
name: version_id
|
|
25
|
-
schema:
|
|
26
|
-
type: string
|
|
27
|
-
description: Dataset version ID. If omitted, returns the latest version.
|
|
28
|
-
responses:
|
|
29
|
-
200:
|
|
30
|
-
description: Success
|
|
31
|
-
content:
|
|
32
|
-
application/json:
|
|
33
|
-
schema:
|
|
34
|
-
type: object
|
|
35
|
-
properties:
|
|
36
|
-
data:
|
|
37
|
-
type: object
|
|
38
|
-
properties:
|
|
39
|
-
dataset_id:
|
|
40
|
-
type: string
|
|
41
|
-
description: ID of the dataset
|
|
42
|
-
version_id:
|
|
43
|
-
type: string
|
|
44
|
-
description: ID of the version
|
|
45
|
-
examples:
|
|
46
|
-
type: array
|
|
47
|
-
items:
|
|
48
|
-
type: object
|
|
49
|
-
properties:
|
|
50
|
-
id:
|
|
51
|
-
type: string
|
|
52
|
-
description: ID of the dataset example
|
|
53
|
-
input:
|
|
54
|
-
type: object
|
|
55
|
-
description: Input data of the example
|
|
56
|
-
output:
|
|
57
|
-
type: object
|
|
58
|
-
description: Output data of the example
|
|
59
|
-
metadata:
|
|
60
|
-
type: object
|
|
61
|
-
description: Metadata of the example
|
|
62
|
-
updated_at:
|
|
63
|
-
type: string
|
|
64
|
-
format: date-time
|
|
65
|
-
description: ISO formatted timestamp of when the example was updated
|
|
66
|
-
required:
|
|
67
|
-
- id
|
|
68
|
-
- input
|
|
69
|
-
- output
|
|
70
|
-
- metadata
|
|
71
|
-
- updated_at
|
|
72
|
-
required:
|
|
73
|
-
- dataset_id
|
|
74
|
-
- version_id
|
|
75
|
-
- examples
|
|
76
|
-
403:
|
|
77
|
-
description: Forbidden
|
|
78
|
-
404:
|
|
79
|
-
description: Dataset does not exist.
|
|
80
|
-
"""
|
|
81
|
-
dataset_id = GlobalID.from_id(request.path_params["id"])
|
|
82
|
-
raw_version_id = request.query_params.get("version_id")
|
|
83
|
-
version_id = GlobalID.from_id(raw_version_id) if raw_version_id else None
|
|
84
|
-
|
|
85
|
-
if (dataset_type := dataset_id.type_name) != "Dataset":
|
|
86
|
-
return Response(
|
|
87
|
-
content=f"ID {dataset_id} refers to a {dataset_type}", status_code=HTTP_404_NOT_FOUND
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
if version_id and (version_type := version_id.type_name) != "DatasetVersion":
|
|
91
|
-
return Response(
|
|
92
|
-
content=f"ID {version_id} refers to a {version_type}", status_code=HTTP_404_NOT_FOUND
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
async with request.app.state.db() as session:
|
|
96
|
-
if (
|
|
97
|
-
resolved_dataset_id := await session.scalar(
|
|
98
|
-
select(Dataset.id).where(Dataset.id == int(dataset_id.node_id))
|
|
99
|
-
)
|
|
100
|
-
) is None:
|
|
101
|
-
return Response(
|
|
102
|
-
content=f"No dataset with id {dataset_id} can be found.",
|
|
103
|
-
status_code=HTTP_404_NOT_FOUND,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
# Subquery to find the maximum created_at for each dataset_example_id
|
|
107
|
-
# timestamp tiebreaks are resolved by the largest id
|
|
108
|
-
partial_subquery = select(
|
|
109
|
-
func.max(DatasetExampleRevision.id).label("max_id"),
|
|
110
|
-
).group_by(DatasetExampleRevision.dataset_example_id)
|
|
111
|
-
|
|
112
|
-
if version_id:
|
|
113
|
-
if (
|
|
114
|
-
resolved_version_id := await session.scalar(
|
|
115
|
-
select(DatasetVersion.id).where(
|
|
116
|
-
and_(
|
|
117
|
-
DatasetVersion.dataset_id == resolved_dataset_id,
|
|
118
|
-
DatasetVersion.id == int(version_id.node_id),
|
|
119
|
-
)
|
|
120
|
-
)
|
|
121
|
-
)
|
|
122
|
-
) is None:
|
|
123
|
-
return Response(
|
|
124
|
-
content=f"No dataset version with id {version_id} can be found.",
|
|
125
|
-
status_code=HTTP_404_NOT_FOUND,
|
|
126
|
-
)
|
|
127
|
-
# if a version_id is provided, filter the subquery to only include revisions from that
|
|
128
|
-
partial_subquery = partial_subquery.filter(
|
|
129
|
-
DatasetExampleRevision.dataset_version_id <= resolved_version_id
|
|
130
|
-
)
|
|
131
|
-
else:
|
|
132
|
-
if (
|
|
133
|
-
resolved_version_id := await session.scalar(
|
|
134
|
-
select(func.max(DatasetVersion.id)).where(
|
|
135
|
-
DatasetVersion.dataset_id == resolved_dataset_id
|
|
136
|
-
)
|
|
137
|
-
)
|
|
138
|
-
) is None:
|
|
139
|
-
return Response(
|
|
140
|
-
content="Dataset has no versions.",
|
|
141
|
-
status_code=HTTP_404_NOT_FOUND,
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
subquery = partial_subquery.subquery()
|
|
145
|
-
# Query for the most recent example revisions that are not deleted
|
|
146
|
-
query = (
|
|
147
|
-
select(DatasetExample, DatasetExampleRevision)
|
|
148
|
-
.join(
|
|
149
|
-
DatasetExampleRevision,
|
|
150
|
-
DatasetExample.id == DatasetExampleRevision.dataset_example_id,
|
|
151
|
-
)
|
|
152
|
-
.join(
|
|
153
|
-
subquery,
|
|
154
|
-
(subquery.c.max_id == DatasetExampleRevision.id),
|
|
155
|
-
)
|
|
156
|
-
.filter(DatasetExample.dataset_id == resolved_dataset_id)
|
|
157
|
-
.filter(DatasetExampleRevision.revision_kind != "DELETE")
|
|
158
|
-
.order_by(DatasetExample.id.asc())
|
|
159
|
-
)
|
|
160
|
-
examples = [
|
|
161
|
-
{
|
|
162
|
-
"id": str(GlobalID("DatasetExample", str(example.id))),
|
|
163
|
-
"input": revision.input,
|
|
164
|
-
"output": revision.output,
|
|
165
|
-
"metadata": revision.metadata_,
|
|
166
|
-
"updated_at": revision.created_at.isoformat(),
|
|
167
|
-
}
|
|
168
|
-
async for example, revision in await session.stream(query)
|
|
169
|
-
]
|
|
170
|
-
return JSONResponse(
|
|
171
|
-
{
|
|
172
|
-
"data": {
|
|
173
|
-
"dataset_id": str(GlobalID("Dataset", str(resolved_dataset_id))),
|
|
174
|
-
"version_id": str(GlobalID("DatasetVersion", str(resolved_version_id))),
|
|
175
|
-
"examples": examples,
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
)
|
phoenix/server/openapi/docs.py
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Any, Dict, Optional
|
|
3
|
-
|
|
4
|
-
from starlette.responses import HTMLResponse
|
|
5
|
-
|
|
6
|
-
swagger_ui_default_parameters: Dict[str, Any] = {
|
|
7
|
-
"dom_id": "#swagger-ui",
|
|
8
|
-
"layout": "BaseLayout",
|
|
9
|
-
"deepLinking": True,
|
|
10
|
-
"showExtensions": True,
|
|
11
|
-
"showCommonExtensions": True,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def get_swagger_ui_html(
|
|
16
|
-
*,
|
|
17
|
-
openapi_url: str = "/schema",
|
|
18
|
-
title: str,
|
|
19
|
-
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui-bundle.js",
|
|
20
|
-
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.9.0/swagger-ui.css",
|
|
21
|
-
swagger_favicon_url: str = "/favicon.ico",
|
|
22
|
-
oauth2_redirect_url: Optional[str] = None,
|
|
23
|
-
init_oauth: Optional[str] = None,
|
|
24
|
-
swagger_ui_parameters: Optional[Dict[str, Any]] = None,
|
|
25
|
-
) -> HTMLResponse:
|
|
26
|
-
"""
|
|
27
|
-
Generate and return the HTML that loads Swagger UI for the interactive API
|
|
28
|
-
docs (normally served at `/docs`).
|
|
29
|
-
"""
|
|
30
|
-
current_swagger_ui_parameters = swagger_ui_default_parameters.copy()
|
|
31
|
-
if swagger_ui_parameters:
|
|
32
|
-
current_swagger_ui_parameters.update(swagger_ui_parameters)
|
|
33
|
-
|
|
34
|
-
html = f"""
|
|
35
|
-
<!DOCTYPE html>
|
|
36
|
-
<html>
|
|
37
|
-
<head>
|
|
38
|
-
<link type="text/css" rel="stylesheet" href="{swagger_css_url}">
|
|
39
|
-
<link rel="shortcut icon" href="{swagger_favicon_url}">
|
|
40
|
-
<title>{title}</title>
|
|
41
|
-
</head>
|
|
42
|
-
<body>
|
|
43
|
-
<div id="swagger-ui">
|
|
44
|
-
</div>
|
|
45
|
-
<script src="{swagger_js_url}"></script>
|
|
46
|
-
<style type="text/css">
|
|
47
|
-
div[id^="operations-private"]{{display:none}} #operations-tag-private{{display:none}}
|
|
48
|
-
</style>
|
|
49
|
-
<!-- `SwaggerUIBundle` is now available on the page -->
|
|
50
|
-
<script>
|
|
51
|
-
const ui = SwaggerUIBundle({{
|
|
52
|
-
url: '{openapi_url}',
|
|
53
|
-
"""
|
|
54
|
-
|
|
55
|
-
for key, value in current_swagger_ui_parameters.items():
|
|
56
|
-
html += f"{json.dumps(key)}: {json.dumps(value)},\n"
|
|
57
|
-
|
|
58
|
-
if oauth2_redirect_url:
|
|
59
|
-
html += f"oauth2RedirectUrl: window.location.origin + '{oauth2_redirect_url}',"
|
|
60
|
-
|
|
61
|
-
html += """
|
|
62
|
-
presets: [
|
|
63
|
-
SwaggerUIBundle.presets.apis,
|
|
64
|
-
SwaggerUIBundle.SwaggerUIStandalonePreset
|
|
65
|
-
],
|
|
66
|
-
})"""
|
|
67
|
-
|
|
68
|
-
if init_oauth:
|
|
69
|
-
html += f"""
|
|
70
|
-
ui.initOAuth({json.dumps(init_oauth)})
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
html += """
|
|
74
|
-
</script>
|
|
75
|
-
</body>
|
|
76
|
-
</html>
|
|
77
|
-
"""
|
|
78
|
-
return HTMLResponse(html)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def get_redoc_html(
|
|
82
|
-
*,
|
|
83
|
-
openapi_url: str,
|
|
84
|
-
title: str,
|
|
85
|
-
redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js",
|
|
86
|
-
redoc_favicon_url: str = "/favicon.ico",
|
|
87
|
-
with_google_fonts: bool = True,
|
|
88
|
-
) -> HTMLResponse:
|
|
89
|
-
"""
|
|
90
|
-
Generate and return the HTML response that loads ReDoc for the alternative
|
|
91
|
-
API docs (normally served at `/redoc`).
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"""
|
|
95
|
-
html = f"""
|
|
96
|
-
<!DOCTYPE html>
|
|
97
|
-
<html>
|
|
98
|
-
<head>
|
|
99
|
-
<title>{title}</title>
|
|
100
|
-
<!-- needed for adaptive design -->
|
|
101
|
-
<meta charset="utf-8"/>
|
|
102
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
103
|
-
"""
|
|
104
|
-
if with_google_fonts:
|
|
105
|
-
html += """
|
|
106
|
-
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
107
|
-
""" # noqa: E501
|
|
108
|
-
html += f"""
|
|
109
|
-
<link rel="shortcut icon" href="{redoc_favicon_url}">
|
|
110
|
-
<!--
|
|
111
|
-
ReDoc doesn't change outer page styles
|
|
112
|
-
-->
|
|
113
|
-
<style>
|
|
114
|
-
body {{
|
|
115
|
-
margin: 0;
|
|
116
|
-
padding: 0;
|
|
117
|
-
}}
|
|
118
|
-
</style>
|
|
119
|
-
</head>
|
|
120
|
-
<body>
|
|
121
|
-
<noscript>
|
|
122
|
-
ReDoc requires Javascript to function. Please enable it to browse the documentation.
|
|
123
|
-
</noscript>
|
|
124
|
-
<redoc spec-url="{openapi_url}"></redoc>
|
|
125
|
-
<script src="{redoc_js_url}"> </script>
|
|
126
|
-
</body>
|
|
127
|
-
</html>
|
|
128
|
-
"""
|
|
129
|
-
return HTMLResponse(html)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# Not needed now but copy-pasting for future reference
|
|
133
|
-
def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse:
|
|
134
|
-
"""
|
|
135
|
-
Generate the HTML response with the OAuth2 redirection for Swagger UI.
|
|
136
|
-
|
|
137
|
-
You normally don't need to use or change this.
|
|
138
|
-
"""
|
|
139
|
-
# copied from https://github.com/swagger-api/swagger-ui/blob/v4.14.0/dist/oauth2-redirect.html
|
|
140
|
-
html = """
|
|
141
|
-
<!doctype html>
|
|
142
|
-
<html lang="en-US">
|
|
143
|
-
<head>
|
|
144
|
-
<title>Swagger UI: OAuth2 Redirect</title>
|
|
145
|
-
</head>
|
|
146
|
-
<body>
|
|
147
|
-
<script>
|
|
148
|
-
'use strict';
|
|
149
|
-
function run () {
|
|
150
|
-
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
|
151
|
-
var sentState = oauth2.state;
|
|
152
|
-
var redirectUrl = oauth2.redirectUrl;
|
|
153
|
-
var isValid, qp, arr;
|
|
154
|
-
|
|
155
|
-
if (/code|token|error/.test(window.location.hash)) {
|
|
156
|
-
qp = window.location.hash.substring(1).replace('?', '&');
|
|
157
|
-
} else {
|
|
158
|
-
qp = location.search.substring(1);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
arr = qp.split("&");
|
|
162
|
-
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
|
163
|
-
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
|
164
|
-
function (key, value) {
|
|
165
|
-
return key === "" ? value : decodeURIComponent(value);
|
|
166
|
-
}
|
|
167
|
-
) : {};
|
|
168
|
-
|
|
169
|
-
isValid = qp.state === sentState;
|
|
170
|
-
|
|
171
|
-
if ((
|
|
172
|
-
oauth2.auth.schema.get("flow") === "accessCode" ||
|
|
173
|
-
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
|
174
|
-
oauth2.auth.schema.get("flow") === "authorization_code"
|
|
175
|
-
) && !oauth2.auth.code) {
|
|
176
|
-
if (!isValid) {
|
|
177
|
-
oauth2.errCb({
|
|
178
|
-
authId: oauth2.auth.name,
|
|
179
|
-
source: "auth",
|
|
180
|
-
level: "warning",
|
|
181
|
-
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (qp.code) {
|
|
186
|
-
delete oauth2.state;
|
|
187
|
-
oauth2.auth.code = qp.code;
|
|
188
|
-
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
|
189
|
-
} else {
|
|
190
|
-
let oauthErrorMsg;
|
|
191
|
-
if (qp.error) {
|
|
192
|
-
oauthErrorMsg = "["+qp.error+"]: " +
|
|
193
|
-
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
|
194
|
-
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
oauth2.errCb({
|
|
198
|
-
authId: oauth2.auth.name,
|
|
199
|
-
source: "auth",
|
|
200
|
-
level: "error",
|
|
201
|
-
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
} else {
|
|
205
|
-
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
|
206
|
-
}
|
|
207
|
-
window.close();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (document.readyState !== 'loading') {
|
|
211
|
-
run();
|
|
212
|
-
} else {
|
|
213
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
214
|
-
run();
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
</script>
|
|
218
|
-
</body>
|
|
219
|
-
</html>
|
|
220
|
-
""" # noqa: E501
|
|
221
|
-
return HTMLResponse(content=html)
|