Skip to content

Commit 3b2027b

Browse files
authored
List license and its url on public dataset (#1046)
* public license and url working now * decorate an endpoint to allow public and private routes
1 parent 08a4795 commit 3b2027b

File tree

8 files changed

+245
-2
lines changed

8 files changed

+245
-2
lines changed

backend/app/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@
237237
tags=["licenses"],
238238
dependencies=[Depends(get_current_username)],
239239
)
240+
api_router.include_router(
241+
licenses.public_router, prefix="/public_licenses", tags=["public_licenses"]
242+
)
240243
api_router.include_router(status.router, prefix="/status", tags=["status"])
241244
api_router.include_router(keycloak.router, prefix="/auth", tags=["auth"])
242245
app.include_router(api_router, prefix=settings.API_V2_STR)

backend/app/routers/licenses.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from fastapi import APIRouter, Depends, HTTPException
1616

1717
router = APIRouter()
18+
public_router = APIRouter()
1819

1920

2021
@router.post("", response_model=LicenseOut)
@@ -29,6 +30,7 @@ async def save_license(
2930
return license_db.dict()
3031

3132

33+
@public_router.get("/{license_id}", response_model=LicenseOut)
3234
@router.get("/{license_id}", response_model=LicenseOut)
3335
async def get_license(license_id: str):
3436
if (license := await LicenseDB.get(PydanticObjectId(license_id))) is not None:
@@ -39,11 +41,13 @@ async def get_license(license_id: str):
3941

4042

4143
# Endpoint to retrieve standard license options
44+
@public_router.get("/standard_licenses/all", response_model=List[LicenseOption])
4245
@router.get("/standard_licenses/all", response_model=List[LicenseOption])
4346
def get_standard_licenses():
4447
return standard_licenses
4548

4649

50+
@public_router.get("/standard_licenses/{license_id}", response_model=str)
4751
@router.get("/standard_licenses/{license_id}", response_model=str)
4852
def get_standard_license_url(license_id: str):
4953
for license in standard_licenses:

backend/app/tests/test_license.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,22 @@ def test_license(client: TestClient, headers: dict):
1919
assert response.status_code == 200
2020
license_id = response.json().get("id")
2121

22-
# get
22+
# private get without token should fail
23+
response = client.get(f"{settings.API_V2_STR}/licenses/{license_id}")
24+
assert response.status_code == 401
25+
26+
# private get with token should pass
2327
response = client.get(
2428
f"{settings.API_V2_STR}/licenses/{license_id}", headers=headers
2529
)
2630
assert response.status_code == 200
2731

32+
# public get route without token should pass
33+
response = client.get(
34+
f"{settings.API_V2_STR}/public_licenses/{license_id}" # , headers=headers
35+
)
36+
assert response.status_code == 200
37+
2838
# edit
2939
license_info = response.json()
3040
license_info["version"] = "1.1"

frontend/src/components/datasets/PublicDataset.tsx

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { ChangeEvent, useEffect, useState } from "react";
33
import {
44
Box,
55
Grid,
6+
Link,
67
Pagination,
78
Stack,
89
Tab,
@@ -38,6 +39,7 @@ import { ErrorModal } from "../errors/ErrorModal";
3839
import { Visualization } from "../visualizations/Visualization";
3940
import VisibilityIcon from "@mui/icons-material/Visibility";
4041
import config from "../../app.config";
42+
import { fetchPublicStandardLicenseUrl } from "../../utils/licenses";
4143

4244
export const PublicDataset = (): JSX.Element => {
4345
// path parameter
@@ -79,10 +81,19 @@ export const PublicDataset = (): JSX.Element => {
7981
const about = useSelector(
8082
(state: RootState) => state.publicDataset.publicAbout
8183
);
82-
8384
const publicFolderPath = useSelector(
8485
(state: RootState) => state.folder.publicFolderPath
8586
);
87+
const license = useSelector((state: RootState) => state.dataset.license);
88+
const [standardLicenseUrl, setStandardLicenseUrl] = useState<string>("");
89+
const fetchStandardLicenseUrlData = async (license_id: string) => {
90+
try {
91+
const data = await fetchPublicStandardLicenseUrl(license_id); // Call your function to fetch licenses
92+
setStandardLicenseUrl(data); // Update state with the fetched data
93+
} catch (error) {
94+
console.error("Error fetching license url", error);
95+
}
96+
};
8697

8798
// state
8899
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
@@ -111,6 +122,11 @@ export const PublicDataset = (): JSX.Element => {
111122
getMetadatDefinitions(null, 0, 100);
112123
}, [searchParams]);
113124

125+
useEffect(() => {
126+
if (about && about.license_id !== undefined)
127+
fetchStandardLicenseUrlData(about.license_id);
128+
}, [about]);
129+
114130
// for breadcrumb
115131
useEffect(() => {
116132
// for breadcrumb
@@ -270,6 +286,35 @@ export const PublicDataset = (): JSX.Element => {
270286
</TabPanel>
271287
</Grid>
272288
<Grid item xs={12} sm={12} md={2} lg={2} xl={2}>
289+
<Typography variant="h5" gutterBottom>
290+
License
291+
</Typography>
292+
{about.standard_license && about.license_id !== undefined ? (
293+
<Typography>
294+
<Link href={standardLicenseUrl} target="_blank">
295+
<img
296+
className="logo"
297+
src={`public/${about.license_id}.png`}
298+
alt={about.license_id}
299+
/>
300+
</Link>
301+
</Typography>
302+
) : (
303+
<></>
304+
)}
305+
{!about.standard_license &&
306+
license !== undefined &&
307+
license.name !== undefined ? (
308+
<div>
309+
<Typography>
310+
<Link href={license.url} target="_blank">
311+
{license.name}
312+
</Link>
313+
</Typography>
314+
</div>
315+
) : (
316+
<></>
317+
)}
273318
<DatasetDetails details={about} />
274319
</Grid>
275320
</Grid>

frontend/src/openapi/v2/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export { PublicDatasetsService } from './services/PublicDatasetsService';
9999
export { PublicElasticsearchService } from './services/PublicElasticsearchService';
100100
export { PublicFilesService } from './services/PublicFilesService';
101101
export { PublicFoldersService } from './services/PublicFoldersService';
102+
export { PublicLicensesService } from './services/PublicLicensesService';
102103
export { PublicMetadataService } from './services/PublicMetadataService';
103104
export { PublicVisualizationsService } from './services/PublicVisualizationsService';
104105
export { ServiceService } from './services/ServiceService';
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* istanbul ignore file */
2+
/* tslint:disable */
3+
/* eslint-disable */
4+
import type { LicenseOption } from '../models/LicenseOption';
5+
import type { LicenseOut } from '../models/LicenseOut';
6+
import type { CancelablePromise } from '../core/CancelablePromise';
7+
import { request as __request } from '../core/request';
8+
9+
export class PublicLicensesService {
10+
11+
/**
12+
* Get License
13+
* @param licenseId
14+
* @returns LicenseOut Successful Response
15+
* @throws ApiError
16+
*/
17+
public static getLicenseApiV2PublicLicensesLicenseIdGet(
18+
licenseId: string,
19+
): CancelablePromise<LicenseOut> {
20+
return __request({
21+
method: 'GET',
22+
path: `/api/v2/public_licenses/${licenseId}`,
23+
errors: {
24+
422: `Validation Error`,
25+
},
26+
});
27+
}
28+
29+
/**
30+
* Get Standard Licenses
31+
* @returns LicenseOption Successful Response
32+
* @throws ApiError
33+
*/
34+
public static getStandardLicensesApiV2PublicLicensesStandardLicensesAllGet(): CancelablePromise<Array<LicenseOption>> {
35+
return __request({
36+
method: 'GET',
37+
path: `/api/v2/public_licenses/standard_licenses/all`,
38+
});
39+
}
40+
41+
/**
42+
* Get Standard License Url
43+
* @param licenseId
44+
* @returns string Successful Response
45+
* @throws ApiError
46+
*/
47+
public static getStandardLicenseUrlApiV2PublicLicensesStandardLicensesLicenseIdGet(
48+
licenseId: string,
49+
): CancelablePromise<string> {
50+
return __request({
51+
method: 'GET',
52+
path: `/api/v2/public_licenses/standard_licenses/${licenseId}`,
53+
errors: {
54+
422: `Validation Error`,
55+
},
56+
});
57+
}
58+
59+
}

frontend/src/utils/licenses.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,14 @@ export async function fetchStandardLicenseUrl(licenseId) {
1919
return {};
2020
}
2121
}
22+
23+
export async function fetchPublicStandardLicenseUrl(licenseId) {
24+
try {
25+
return await V2.PublicLicensesService.getStandardLicenseUrlApiV2PublicLicensesStandardLicensesLicenseIdGet(
26+
licenseId
27+
);
28+
} catch (reason) {
29+
console.error("Failed to fetch standard license url: ", reason);
30+
return {};
31+
}
32+
}

openapi.json

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9485,6 +9485,116 @@
94859485
]
94869486
}
94879487
},
9488+
"/api/v2/public_licenses/{license_id}": {
9489+
"get": {
9490+
"tags": [
9491+
"public_licenses"
9492+
],
9493+
"summary": "Get License",
9494+
"operationId": "get_license_api_v2_public_licenses__license_id__get",
9495+
"parameters": [
9496+
{
9497+
"required": true,
9498+
"schema": {
9499+
"title": "License Id",
9500+
"type": "string"
9501+
},
9502+
"name": "license_id",
9503+
"in": "path"
9504+
}
9505+
],
9506+
"responses": {
9507+
"200": {
9508+
"description": "Successful Response",
9509+
"content": {
9510+
"application/json": {
9511+
"schema": {
9512+
"$ref": "#/components/schemas/LicenseOut"
9513+
}
9514+
}
9515+
}
9516+
},
9517+
"422": {
9518+
"description": "Validation Error",
9519+
"content": {
9520+
"application/json": {
9521+
"schema": {
9522+
"$ref": "#/components/schemas/HTTPValidationError"
9523+
}
9524+
}
9525+
}
9526+
}
9527+
}
9528+
}
9529+
},
9530+
"/api/v2/public_licenses/standard_licenses/all": {
9531+
"get": {
9532+
"tags": [
9533+
"public_licenses"
9534+
],
9535+
"summary": "Get Standard Licenses",
9536+
"operationId": "get_standard_licenses_api_v2_public_licenses_standard_licenses_all_get",
9537+
"responses": {
9538+
"200": {
9539+
"description": "Successful Response",
9540+
"content": {
9541+
"application/json": {
9542+
"schema": {
9543+
"title": "Response Get Standard Licenses Api V2 Public Licenses Standard Licenses All Get",
9544+
"type": "array",
9545+
"items": {
9546+
"$ref": "#/components/schemas/LicenseOption"
9547+
}
9548+
}
9549+
}
9550+
}
9551+
}
9552+
}
9553+
}
9554+
},
9555+
"/api/v2/public_licenses/standard_licenses/{license_id}": {
9556+
"get": {
9557+
"tags": [
9558+
"public_licenses"
9559+
],
9560+
"summary": "Get Standard License Url",
9561+
"operationId": "get_standard_license_url_api_v2_public_licenses_standard_licenses__license_id__get",
9562+
"parameters": [
9563+
{
9564+
"required": true,
9565+
"schema": {
9566+
"title": "License Id",
9567+
"type": "string"
9568+
},
9569+
"name": "license_id",
9570+
"in": "path"
9571+
}
9572+
],
9573+
"responses": {
9574+
"200": {
9575+
"description": "Successful Response",
9576+
"content": {
9577+
"application/json": {
9578+
"schema": {
9579+
"title": "Response Get Standard License Url Api V2 Public Licenses Standard Licenses License Id Get",
9580+
"type": "string"
9581+
}
9582+
}
9583+
}
9584+
},
9585+
"422": {
9586+
"description": "Validation Error",
9587+
"content": {
9588+
"application/json": {
9589+
"schema": {
9590+
"$ref": "#/components/schemas/HTTPValidationError"
9591+
}
9592+
}
9593+
}
9594+
}
9595+
}
9596+
}
9597+
},
94889598
"/api/v2/status": {
94899599
"get": {
94909600
"tags": [

0 commit comments

Comments
 (0)