Aligning the project structure with Hello World example
This commit is contained in:
parent
74e05671bf
commit
0970e29e86
|
@ -0,0 +1,27 @@
|
|||
# docker build -t $DOCKER_BUILD_NAME \
|
||||
# --build-arg="MVN_FINALNAME=$MVN_FINALNAME" \
|
||||
# --build-arg="MVN_NAME=${MVN_NAME}" \
|
||||
# --build-arg="CONTAINER_INI=${CONTAINER_INI}" \
|
||||
# --build-arg="JAVA_VERSION=${JAVA_VERSION}" \
|
||||
# --build-arg="SMARTGEARS_VERSION=${SMARTGEARS_VERSION}" \
|
||||
# -f Dockerfile \
|
||||
# $PLATFORMS .
|
||||
|
||||
ARG JAVA_VERSION
|
||||
ARG SMARTGEARS_VERSION
|
||||
|
||||
#FROM d4science/smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-tomcat10.1.19
|
||||
FROM hub.dev.d4science.org/gcube/smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-tomcat10.1.19
|
||||
ARG CONTAINER_INI="./dockerize/configuration/container.ini"
|
||||
ARG MVN_FINALNAME
|
||||
ARG MVN_NAME
|
||||
|
||||
#FROM smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-tomcat10.1.19
|
||||
|
||||
COPY ./dockerize/configuration/logback.xml /etc/
|
||||
COPY ./dockerize/configuration/*.gcubekey /tomcat/lib
|
||||
COPY ./target/${MVN_FINALNAME}.war /tmp
|
||||
RUN unzip /tmp/${MVN_FINALNAME}.war -d /tomcat/webapps/${MVN_NAME}
|
||||
COPY ${CONTAINER_INI} /etc/container.ini
|
||||
|
||||
EXPOSE 8080
|
|
@ -0,0 +1,180 @@
|
|||
#!/bin/bash
|
||||
|
||||
# set -x # uncomment to debug script
|
||||
set -a
|
||||
source ./build_conf
|
||||
set +a
|
||||
|
||||
ACCEPTED_JAVA_VERSIONs=(11 17)
|
||||
PORT=8080
|
||||
DEBUG_PORT=5005
|
||||
DEBUG=false
|
||||
EXECUTE=false
|
||||
TEST=false
|
||||
COMPILE=true
|
||||
|
||||
GOAL="clean package"
|
||||
|
||||
PUSH_DOCKER=false
|
||||
PUSH_HARBOR=false
|
||||
LOGIN_HARBOR=false
|
||||
|
||||
################################################################################
|
||||
# Help #
|
||||
################################################################################
|
||||
Help() {
|
||||
# Display Help
|
||||
echo "build, create and run in docker the identity manager service"
|
||||
echo
|
||||
echo "Syntax: buildDistribution "
|
||||
echo "options:"
|
||||
|
||||
echo "-e execute the docker image"
|
||||
echo "-g arg specifies the maven [g]oals {package, install, deploy etc} default is $GOAL."
|
||||
echo "-d arg? enable java debug mode for execution"
|
||||
|
||||
echo "-r push image to d4science harbo[r] (with login already done, or -l to login)"
|
||||
echo "-u p[u]sh image to dockerhub (with docker login already done)"
|
||||
|
||||
echo "-p arg specifies the port to be exposed for the docker container to access the service (default $PORT)"
|
||||
|
||||
echo "-c arg path of the file to deploy as container.ini (default ./docker/container.ini)"
|
||||
|
||||
echo "-j arg specify java version (default is $JAVA_VERSION)"
|
||||
echo " accepted version are: ${ACCEPTED_JAVA_VERSIONs[@]}"
|
||||
echo " arg is the debug port (default is $DEBUG_PORT)"
|
||||
|
||||
echo "-s skip maven package"
|
||||
echo "-t exec also maven tests"
|
||||
|
||||
echo "-n arg specifies the docker image name (default is $MVN_NAME)."
|
||||
|
||||
echo "-l [l]ogin to d4science harbor"
|
||||
echo "-h Print this Help."
|
||||
echo
|
||||
echo "to compile and push to harbor registry with a custom container.ini file: "
|
||||
echo " ./buildImageAndStart.sh -r -m -l -c \"./docker/container-XXX.ini\" "
|
||||
echo
|
||||
echo "to debug locally: "
|
||||
echo " ./buildImageAndStart.sh -d "
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
# Main program #
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
set -e
|
||||
|
||||
#OPTSTRING=":sn:p:d:j:?h"
|
||||
OPTSTRING=":c:n:p:g:d:?jsmulrteh"
|
||||
|
||||
while getopts $OPTSTRING opt; do
|
||||
# echo "Option -${opt} was triggered, Argument: ${OPTARG}"
|
||||
case "${opt}" in
|
||||
s) COMPILE=false && echo "compile $COMPILE" ;;
|
||||
g) GOAL=${OPTARG} ;;
|
||||
c)
|
||||
CONTAINER_INI=${OPTARG}
|
||||
echo "CONTAINER_INI: $CONTAINER_INI"
|
||||
;;
|
||||
m) MULTI_PLATFORM=true ;;
|
||||
n) NAME=${OPTARG} ;;
|
||||
p) PORT=${OPTARG} ;;
|
||||
|
||||
u) PUSH_DOCKER=true ;;
|
||||
l) LOGIN_HARBOR=true ;;
|
||||
r) PUSH_HARBOR=true ;;
|
||||
|
||||
t) TEST=true ;;
|
||||
e) EXECUTE=true ;;
|
||||
d)
|
||||
DEBUG=true
|
||||
DEBUG_PORT=${OPTARG}
|
||||
echo "debug enabled, port $DEBUG_PORT, execute $EXECUTE"
|
||||
;;
|
||||
j)
|
||||
if [[ ${ACCEPTED_JAVA_VERSIONs[@]} =~ ${OPTARG} ]]; then
|
||||
JAVA_VERSION=${OPTARG}
|
||||
else
|
||||
echo "Invalid java version" && echo "accepted version are: ${ACCEPTED_JAVA_VERSIONs[@]}" && exit 1
|
||||
fi
|
||||
;;
|
||||
h) Help && exit 0 ;;
|
||||
|
||||
:)
|
||||
# matched when an option that is expected to have an argument is passed without one
|
||||
if [ ${OPTARG} = "d" ]; then
|
||||
DEBUG=true
|
||||
EXECUTE=true
|
||||
echo "debug enabled, port $DEBUG_PORT"
|
||||
else
|
||||
# matched when an option that is expected to have an argument is passed without one
|
||||
echo "Option -${OPTARG} requires an argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
?) # match any invalid option that is passed
|
||||
echo "Invalid option: -${OPTARG}."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $COMPILE = true ]; then
|
||||
SKIP_TEST=""
|
||||
if [ $TEST = false ]; then
|
||||
SKIP_TEST="-Dmaven.test.skip"
|
||||
fi
|
||||
|
||||
( cd .. && mvn $GOAL $SKIP_TEST );
|
||||
else
|
||||
echo "skipping mvn package"
|
||||
fi
|
||||
|
||||
echo "SMARTGEAR IMAGE: $SMARTGEAR_IMAGE"
|
||||
docker pull $SMARTGEAR_IMAGE
|
||||
|
||||
if [ $MULTI_PLATFORM ]; then
|
||||
PLATFORMS="--platform=linux/amd64,linux/arm64,linux/arm/v7"
|
||||
echo "build multiple platform $PLATFORMS"
|
||||
fi
|
||||
|
||||
echo "DOCKER_BUILD_NAME: $DOCKER_BUILD_NAME"
|
||||
|
||||
( cd .. && docker build -t $DOCKER_BUILD_NAME \
|
||||
--build-arg="MVN_FINALNAME=$MVN_FINALNAME" \
|
||||
--build-arg="MVN_NAME=${MVN_NAME}" \
|
||||
--build-arg="CONTAINER_INI=${CONTAINER_INI}" \
|
||||
--build-arg="JAVA_VERSION=${JAVA_VERSION}" \
|
||||
--build-arg="SMARTGEARS_VERSION=${SMARTGEARS_VERSION}" \
|
||||
-f Dockerfile \
|
||||
$PLATFORMS . );
|
||||
|
||||
if [ ${PUSH_DOCKER} = true ]; then
|
||||
docker tag $DOCKER_BUILD_NAME $DOCKER_IMAGE_NAME
|
||||
docker push $DOCKER_IMAGE_NAME
|
||||
echo ">>> pushed on dockerhub the image $DOCKER_IMAGE_NAME"
|
||||
fi
|
||||
|
||||
if [ ${LOGIN_HARBOR} = true ]; then
|
||||
./loginHarborHub.sh
|
||||
fi
|
||||
|
||||
if [ $PUSH_HARBOR = true ]; then
|
||||
echo ">>> PUSHING on hub.dev.d4science.org the image $HARBOR_IMAGE_NAME"
|
||||
|
||||
docker tag $DOCKER_BUILD_NAME $HARBOR_IMAGE_NAME
|
||||
echo ">>> docker push $HARBOR_IMAGE_NAME"
|
||||
docker push $HARBOR_IMAGE_NAME
|
||||
echo ">>> pushed on hub.dev.d4science.org the image $HARBOR_IMAGE_NAME"
|
||||
fi
|
||||
|
||||
if [ ${EXECUTE} = true ]; then
|
||||
if [ $DEBUG = true ]; then
|
||||
docker run -p $PORT:8080 -p $DEBUG_PORT:5005 -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=*:5005,server=y,suspend=y" $DOCKER_BUILD_NAME
|
||||
else
|
||||
docker run -p $PORT:8080 $DOCKER_BUILD_NAME
|
||||
fi
|
||||
fi
|
|
@ -0,0 +1,55 @@
|
|||
MVN_VERSION=$(cd .. && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${project.version}' \
|
||||
--non-recursive \
|
||||
exec:exec)
|
||||
echo "MVN_VERSION: ${MVN_VERSION}"
|
||||
|
||||
MVN_NAME=$(cd .. && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${project.artifactId}' \
|
||||
--non-recursive \
|
||||
exec:exec)
|
||||
echo "MVN_NAME: ${MVN_NAME}"
|
||||
|
||||
MVN_FINALNAME=$(cd .. && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${project.build.finalName}' \
|
||||
--non-recursive \
|
||||
exec:exec)
|
||||
echo "MVN_FINALNAME: ${MVN_FINALNAME}"
|
||||
|
||||
JAVA_VERSION=$(cd .. && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${maven.compiler.target}' \
|
||||
--non-recursive \
|
||||
exec:exec)
|
||||
echo "JAVA_VERSION: ${JAVA_VERSION}"
|
||||
|
||||
TOMCAT_VERSION=tomcat10.1.19
|
||||
echo "TOMCAT_VERSION: ${TOMCAT_VERSION}"
|
||||
|
||||
SMARTGEARS_VERSION=$(cd .. && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${docker.smartgear.version}' \
|
||||
--non-recursive \
|
||||
exec:exec)
|
||||
echo "SMARTGEARS_VERSION: ${SMARTGEARS_VERSION}"
|
||||
|
||||
CONTAINER_INI="./dockerize/configuration/container.ini"
|
||||
echo "CONTAINER_INI: ${CONTAINER_INI}"
|
||||
|
||||
IMAGE_VERSION=${MVN_VERSION}-java${JAVA_VERSION}-smartgears${SMARTGEARS_VERSION}
|
||||
echo "IMAGE_VERSION: ${IMAGE_VERSION}"
|
||||
|
||||
DOCKER_BUILD_NAME=$MVN_NAME:$IMAGE_VERSION
|
||||
echo "DOCKER_BUILD_NAME: ${DOCKER_BUILD_NAME}"
|
||||
|
||||
SMARTGEAR_IMAGE=hub.dev.d4science.org/gcube/smartgears-distribution:${SMARTGEARS_VERSION}-java${JAVA_VERSION}-${TOMCAT_VERSION}
|
||||
echo "SMARTGEAR_IMAGE: ${SMARTGEAR_IMAGE}"
|
||||
|
||||
DOCKER_IMAGE_NAME=d4science/$DOCKER_BUILD_NAME
|
||||
echo "DOCKER_IMAGE_NAME: ${DOCKER_IMAGE_NAME}"
|
||||
|
||||
HARBOR_IMAGE_NAME=hub.dev.d4science.org/gcube/$DOCKER_BUILD_NAME
|
||||
echo "HARBOR_IMAGE_NAME: ${HARBOR_IMAGE_NAME}"
|
|
@ -0,0 +1,3 @@
|
|||
container*.ini
|
||||
!container.default.ini
|
||||
*.gcubekey
|
|
@ -0,0 +1,26 @@
|
|||
[node]
|
||||
mode = offline
|
||||
hostname = localhost
|
||||
protocol= http
|
||||
port = 8080
|
||||
infrastructure = gcube
|
||||
authorizeChildrenContext = true
|
||||
publicationFrequencyInSeconds = 60
|
||||
|
||||
[properties]
|
||||
SmartGearsDistribution = 4.0.1-SNAPSHOT
|
||||
SmartGearsDistributionBundle = UnBundled
|
||||
|
||||
[site]
|
||||
country = it
|
||||
location = pisa
|
||||
|
||||
[authorization]
|
||||
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
|
||||
factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
|
||||
credentials.class = org.gcube.smartgears.security.SimpleCredentials
|
||||
|
||||
credentials.clientID =
|
||||
credentials.secret =
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<configuration scan="true" debug="true">
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>Ï <pattern>%-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.gcube.service.helloword" level="DEBUG" />
|
||||
<logger name="org.gcube.smartgears" level="DEBUG" />
|
||||
|
||||
<!--
|
||||
<logger name="org.gcube" level="DEBUG" />
|
||||
<logger name="org.gcube.smartgears" level="TRACE" />
|
||||
<logger name="org.gcube.smartgears.handlers" level="TRACE" />
|
||||
<logger name="org.gcube.common.events" level="WARN" />
|
||||
<logger name="org.gcube.data.publishing" level="ERROR" />
|
||||
<logger name="org.gcube.documentstore" level="ERROR" />
|
||||
<logger name="org.gcube.common.core.publisher.is.legacy" level="TRACE" />
|
||||
<logger name="org.gcube.data.access" level="TRACE" />
|
||||
<logger name="org.gcube.data.access.storagehub.handlers" level="DEBUG" />
|
||||
-->
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,12 @@
|
|||
MVN_VERSION: 1.0.0-SNAPSHOT
|
||||
MVN_NAME: hello-world-service
|
||||
MVN_FINALNAME: hello-world-service-1.0.0-SNAPSHOT
|
||||
JAVA_VERSION: 11
|
||||
TOMCAT_VERSION: tomcat10.1.19
|
||||
SMARTGEARS_VERSION: 4.0.1-SNAPSHOT
|
||||
CONTAINER_INI: ./dockerize/configuration/container.ini
|
||||
IMAGE_VERSION: 1.0.0-SNAPSHOT-java11-smartgears4.0.1-SNAPSHOT
|
||||
DOCKER_BUILD_NAME: hello-world-service:1.0.0-SNAPSHOT-java11-smartgears4.0.1-SNAPSHOT
|
||||
SMARTGEAR_IMAGE: hub.dev.d4science.org/gcube/smartgears-distribution:4.0.1-SNAPSHOT-java11-tomcat10.1.19
|
||||
DOCKER_IMAGE_NAME: d4science/hello-world-service:1.0.0-SNAPSHOT-java11-smartgears4.0.1-SNAPSHOT
|
||||
HARBOR_IMAGE_NAME: hub.dev.d4science.org/gcube/hello-world-service:1.0.0-SNAPSHOT-java11-smartgears4.0.1-SNAPSHOT
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
REGISTRY_URL="hub.dev.d4science.org"
|
||||
#USERNAME="alfredo.oliviero"
|
||||
echo "to obtain Harbor username and CLI secret:"
|
||||
echo "https://hub.dev.d4science.org/ -> user profile -> CLI secret"
|
||||
|
||||
read -p "username:" USERNAME
|
||||
|
||||
echo ""
|
||||
|
||||
read -s -p "CLI secret:" ACCESS_TOKEN
|
||||
echo "$ACCESS_TOKEN" | docker login $REGISTRY_URL -u $USERNAME --password-stdin
|
||||
unset ACCESS_TOKEN
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -a
|
||||
# source build_conf > docker.conf # generate current conf
|
||||
# source docker.conf
|
||||
source build_conf
|
||||
|
||||
docker pull $HARBOR_IMAGE_NAME
|
||||
|
||||
echo "Docker image $HARBOR_IMAGE_NAME"
|
||||
|
||||
set +a
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -a
|
||||
# source build_conf > docker.conf # generate current conf
|
||||
# source docker.conf
|
||||
source build_conf
|
||||
|
||||
echo "Docker image $HARBOR_IMAGE_NAME"
|
||||
docker pull $HARBOR_IMAGE_NAME
|
||||
docker run -d -p 9991:8080 --name $NAME $HARBOR_IMAGE_NAME
|
||||
|
||||
set +a
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -a
|
||||
# source build_conf > docker.conf # generate current conf
|
||||
# source docker.conf
|
||||
source build_conf
|
||||
|
||||
docker stop $NAME
|
||||
docker rm $NAME
|
||||
|
||||
set +a
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
|
||||
[visual studio code - Dev Containers tutorial](https://code.visualstudio.com/docs/devcontainers/tutorial)
|
||||
|
||||
installare su vscode estensione [Dev Containers extension](vscode:extension/ms-vscode-remote.remote-containers)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<enunciate
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.14.0.xsd">
|
||||
<description package="org.gcube.service.idm" />
|
||||
<api-classes>
|
||||
<include pattern="org.gcube.service.helloworld.rest.*" />
|
||||
<exclude pattern="org.gcube.service.helloworld.*" />
|
||||
</api-classes>
|
||||
<modules>
|
||||
<gwt-json-overlay disabled="true" />
|
||||
<php-json-client disabled="true" />
|
||||
<ruby-json-client disabled="true" />
|
||||
<java-json-client disabled="true" />
|
||||
<javascript-client disabled="false" />
|
||||
|
||||
<c-xml-client disabled="true" />
|
||||
<csharp-xml-client disabled="true" />
|
||||
<obj-c-xml-client disabled="true" />
|
||||
<php-xml-client disabled="true" />
|
||||
<spring-webnt disabled="true" />
|
||||
|
||||
|
||||
<docs docsDir="${project.build.directory}" docsSubdir="api-docs" />
|
||||
<swagger basePath="/${project.artifactId}" />
|
||||
<docs
|
||||
freemarkerTemplate="${project.basedir}/src/main/resources/META-INF/enunciate/d4science_docs.fmt">
|
||||
<additional-css
|
||||
file="css/d4science_enunciate_custom.css" />
|
||||
</docs>
|
||||
</modules>
|
||||
</enunciate>
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"id": "ff7036fd-e12d-4dd7-9d0f-816bb5a0f06a",
|
||||
"name": "Hello World Env for devVRE",
|
||||
"values": [
|
||||
{
|
||||
"key": "introspect_secret",
|
||||
"value": "",
|
||||
"type": "secret",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "",
|
||||
"type": "secret",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "service_client_secret",
|
||||
"value": "",
|
||||
"type": "secret",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "realm",
|
||||
"value": "d4science",
|
||||
"type": "any",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "username",
|
||||
"value": "luca.frosini",
|
||||
"type": "default",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "service_client_id",
|
||||
"value": "id.d4science.org",
|
||||
"type": "default",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "context",
|
||||
"value": "/gcube/devsec/devVRE",
|
||||
"type": "default",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "keycloak_url",
|
||||
"value": "https://accounts.dev.d4science.org/auth",
|
||||
"type": "any",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "encoded_context",
|
||||
"value": "%2Fgcube%2Fdevsec%2FdevVRE",
|
||||
"type": "any",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "client-id-user",
|
||||
"value": "next.d4science.org",
|
||||
"type": "default",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"key": "introspect_client",
|
||||
"value": "token-exchange-dedicated",
|
||||
"type": "default",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"_postman_variable_scope": "environment",
|
||||
"_postman_exported_at": "2024-05-24T16:06:23.560Z",
|
||||
"_postman_exported_using": "Postman/11.1.14"
|
||||
}
|
|
@ -0,0 +1,692 @@
|
|||
{
|
||||
"info": {
|
||||
"_postman_id": "e152bab3-7be5-4fe2-81bd-625fec76373d",
|
||||
"name": "Hello World Service",
|
||||
"description": "An example collection that can be used for communicating with gcube services\n\nget TOKEN and at UMA_TOKEN from url: [https://next.dev.d4science.org/group/gcube/home](https://next.dev.d4science.org/group/gcube/home)\n\nupdate the collection's variables gcube_token and uma_token",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||
"_exporter_id": "3092110"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "LOGIN",
|
||||
"item": [
|
||||
{
|
||||
"name": "Clear Env",
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"exec": [
|
||||
"console.log(\"executing clear script\");",
|
||||
"",
|
||||
"variables = [",
|
||||
" 'token',",
|
||||
" 'access_token',",
|
||||
" 'refresh_token',",
|
||||
"",
|
||||
" 'uma_token',",
|
||||
" 'uma_refresh',",
|
||||
"",
|
||||
" 'profile_token',",
|
||||
" 'gcube_token',",
|
||||
" 'oidc_access_token',",
|
||||
" 'oidc_refresh_token',",
|
||||
" 'id_token',",
|
||||
"",
|
||||
" 'clientId',",
|
||||
"",
|
||||
" 'current_username',",
|
||||
" 'current_password',",
|
||||
" 'current_context',",
|
||||
" 'current_url-encoded-context',",
|
||||
" 'current_iam-url',",
|
||||
" 'current_client-id',",
|
||||
" 'current_uma-token',",
|
||||
" 'current_access-token',",
|
||||
"",
|
||||
" 'oidc_token',",
|
||||
" 'oidc_access_token',",
|
||||
" 'oidc_refresh_token',",
|
||||
" 'uma_token',",
|
||||
" 'exchanged_token'",
|
||||
"",
|
||||
"]",
|
||||
"",
|
||||
"for (var v of variables) {",
|
||||
" pm.environment.unset(v);",
|
||||
" pm.globals.unset(v);",
|
||||
"}",
|
||||
"",
|
||||
" ",
|
||||
"",
|
||||
"",
|
||||
" ",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript",
|
||||
"packages": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "/",
|
||||
"path": [
|
||||
""
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get User Token For Context",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"var jsonData = JSON.parse(responseBody);",
|
||||
"postman.setEnvironmentVariable(\"oidc_access_token\", jsonData.access_token);",
|
||||
"postman.setEnvironmentVariable(\"oidc_refresh_token\", jsonData.refresh_token);",
|
||||
"",
|
||||
"postman.setEnvironmentVariable(\"uma_token\", jsonData.access_token);",
|
||||
"",
|
||||
"postman.setEnvironmentVariable(\"access_token\", jsonData.access_token);",
|
||||
"postman.setEnvironmentVariable(\"refresh_token\", jsonData.refresh_token);",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript",
|
||||
"packages": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"exec": [
|
||||
""
|
||||
],
|
||||
"type": "text/javascript",
|
||||
"packages": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/x-www-form-urlencoded"
|
||||
},
|
||||
{
|
||||
"key": "X-D4Science-Context",
|
||||
"value": "{{encoded_context}}"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "urlencoded",
|
||||
"urlencoded": [
|
||||
{
|
||||
"key": "client_id",
|
||||
"value": "{{service_client_id}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "username",
|
||||
"value": "{{username}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "{{password}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "grant_type",
|
||||
"value": "password",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "client_secret",
|
||||
"value": "{{service_client_secret}}",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{keycloak_url}}/realms/{{realm}}/protocol/openid-connect/token",
|
||||
"host": [
|
||||
"{{keycloak_url}}"
|
||||
],
|
||||
"path": [
|
||||
"realms",
|
||||
"{{realm}}",
|
||||
"protocol",
|
||||
"openid-connect",
|
||||
"token"
|
||||
]
|
||||
},
|
||||
"description": "Obtain UAT = user access token from a user in realm"
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Get ClientId Token For Context",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"var jsonData = JSON.parse(responseBody);",
|
||||
"",
|
||||
"// postman.setEnvironmentVariable(\"refresh_token\", jsonData.refresh_token);",
|
||||
"// postman.setEnvironmentVariable(\"id_token\", jsonData.id_token);",
|
||||
"",
|
||||
"postman.setEnvironmentVariable(\"oidc_access_token\", jsonData.access_token);",
|
||||
"",
|
||||
"postman.setEnvironmentVariable(\"access_token\", jsonData.access_token);",
|
||||
"postman.setEnvironmentVariable(\"token\", jsonData.access_token);",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript",
|
||||
"packages": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/x-www-form-urlencoded"
|
||||
},
|
||||
{
|
||||
"key": "X-D4Science-Context",
|
||||
"value": "{{encoded_context}}"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "urlencoded",
|
||||
"urlencoded": [
|
||||
{
|
||||
"key": "client_id",
|
||||
"value": "{{service_client_id}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "client_secret",
|
||||
"value": "{{service_client_secret}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "grant_type",
|
||||
"value": "client_credentials",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{keycloak_url}}/realms/{{realm}}/protocol/openid-connect/token",
|
||||
"host": [
|
||||
"{{keycloak_url}}"
|
||||
],
|
||||
"path": [
|
||||
"realms",
|
||||
"{{realm}}",
|
||||
"protocol",
|
||||
"openid-connect",
|
||||
"token"
|
||||
]
|
||||
},
|
||||
"description": "Obtain SAT (service account token)"
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Validate Access Token",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Basic YWxmcmVkby1pZG0tc2VydmljZS1kZXY6OTc5YmQzYmMtNWNjNC0xMWVjLWJmNjMtMDI0MmFjMTMwMDAy"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "urlencoded",
|
||||
"urlencoded": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "{{access_token}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "username\n",
|
||||
"value": "{{introspect_client}}",
|
||||
"type": "text",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "{{introspect_secret}}",
|
||||
"type": "text",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"key": "client_id",
|
||||
"value": "{{introspect_client}}",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "client_secret",
|
||||
"value": "{{introspect_secret}}",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{keycloak_url}}/realms/{{realm}}/protocol/openid-connect/token/introspect",
|
||||
"host": [
|
||||
"{{keycloak_url}}"
|
||||
],
|
||||
"path": [
|
||||
"realms",
|
||||
"{{realm}}",
|
||||
"protocol",
|
||||
"openid-connect",
|
||||
"token",
|
||||
"introspect"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "REST",
|
||||
"item": [
|
||||
{
|
||||
"name": "authorized",
|
||||
"item": [
|
||||
{
|
||||
"name": "legacy-token",
|
||||
"item": [
|
||||
{
|
||||
"name": "hello TOKEN PARAM",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "",
|
||||
"value": "{{token}}"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/hello?gcube-token={{gcube_token}}",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"hello"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "gcube-token",
|
||||
"value": "{{gcube_token}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "details TOKEN PARAM",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/details?gcube-token={{gcube_token}}",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"details"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "gcube-token",
|
||||
"value": "{{gcube_token}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "auth org member TOKEN PARAM",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/auth/org_member?gcube-token={{gcube_token}}",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"auth",
|
||||
"org_member"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "gcube-token",
|
||||
"value": "{{gcube_token}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "auth member TOKEN PARAM",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/auth/member?gcube-token={{gcube_token}}",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"auth",
|
||||
"member"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "gcube-token",
|
||||
"value": "{{gcube_token}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hello",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/hello",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"hello"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "details",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/details",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"details"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "auth org member",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "{{uma_token}}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/auth/org_member",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"auth",
|
||||
"org_member"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "auth member",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "{{uma_token}}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/auth/member",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"auth",
|
||||
"member"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "No Auth Required",
|
||||
"item": [
|
||||
{
|
||||
"name": "guest",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/guest",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"guest"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "404 Not Found",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/guest/not-found",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"guest",
|
||||
"not-found"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "400 Bad Request",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/guest/bad-request",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"guest",
|
||||
"bad-request"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "PURGE with 204 No Content",
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "PURGE",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{base_url}}/{{application}}/guest/test-purge",
|
||||
"host": [
|
||||
"{{base_url}}"
|
||||
],
|
||||
"path": [
|
||||
"{{application}}",
|
||||
"guest",
|
||||
"test-purge"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "{{access_token}}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"packages": {},
|
||||
"exec": [
|
||||
""
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"packages": {},
|
||||
"exec": [
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"key": "base_url",
|
||||
"value": "http://localhost:8080",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "role_name",
|
||||
"value": "Member"
|
||||
},
|
||||
{
|
||||
"key": "application",
|
||||
"value": "hello-world-service",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "base_url_marco",
|
||||
"value": "http://146.48.85.179:9999",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "base_url_local",
|
||||
"value": "http://localhost:8080",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@ -0,0 +1,62 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
_POM_PATH = "../.."
|
||||
|
||||
def getMvnVariable(variable):
|
||||
cmd = """cd %s && mvn -q \
|
||||
-Dexec.executable=echo \
|
||||
-Dexec.args='${project.%s}' \
|
||||
--non-recursive \
|
||||
exec:exec""" % (_POM_PATH, variable)
|
||||
stream = os.popen(cmd)
|
||||
return stream.read().strip()
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = getMvnVariable("version")
|
||||
project = getMvnVariable("name")
|
||||
|
||||
copyright = '2024, %s' % getMvnVariable("organization.name")
|
||||
author = 'Luca Frosini (ISTI-CNR)'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinxdoc'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
|
@ -0,0 +1,258 @@
|
|||
***********************************************************
|
||||
Welcome to Hello World SG4 documentation
|
||||
***********************************************************
|
||||
|
||||
Hello World SG4 is a RESTful application that exposes operations via REST-API.
|
||||
|
||||
See the available `REST-API docs <../api-docs/index.html>`_.
|
||||
|
||||
Base URL
|
||||
========
|
||||
|
||||
In the production environment, its current value is
|
||||
|
||||
|
||||
Authorization
|
||||
=============
|
||||
|
||||
D4Science adopts state-of-the-art industry standards for authentication and authorization.
|
||||
Specifically, the implementation fully adopts `OIDC (OpenID Connect) <https://openid.net/connect>`_ for authentication and UMA 2 (User-Managed Authorization) for authorization flows.
|
||||
`JSON Web Token (JWT) Access token <https://jwt.io/>`_ are used for both authentication and authorization.
|
||||
|
||||
Obtain your Bearer token here: https://dev.d4science.org/how-to-access-resources
|
||||
|
||||
Service
|
||||
=======
|
||||
|
||||
You can call the methods of the Web Service by writing your REST client application or using existing REST client plugins.
|
||||
|
||||
|
||||
HTTP Statuses
|
||||
-------------
|
||||
|
||||
Any successful operation returns a *200 OK* HTTP status code.
|
||||
The create operation returns *201 Created*.
|
||||
Any Background operation returns *202 Accepted*.
|
||||
Any operation that does not provide any content returns *204 No Content*.
|
||||
|
||||
|
||||
|
||||
The most common error statuses a client can obtain are:
|
||||
|
||||
* **400 Bad Request** used to indicate a clients error `<https://tools.ietf.org/html/rfc7231#section-6.5.1>`_;
|
||||
* **401 Unauthorized** used to indicate that the client does not provide the authorization token in the HTTP Header or the client does not have enough right to perform such request `<https://tools.ietf.org/html/rfc7235#section-3.1>`_;
|
||||
* **404 Not Found** used to indicate that the requested instance does not exist `<https://tools.ietf.org/html/rfc7231#section-6.5.4>`_;
|
||||
* **405 Method Not Allowed** the used HTTP method is not supported for the requested URL `<https://tools.ietf.org/html/rfc7231#section-6.5.5>`_.
|
||||
The response contains the *Allow* HTTP Header indicating the supported HTTP method for such URL `<https://tools.ietf.org/html/rfc7231#section-7.4.1>`_;
|
||||
* **409 Conflict** the request could not be completed due to a conflict with the current state of the target resource (e.g. the name of the resource already exists) `<https://tools.ietf.org/html/rfc7231#section-6.5.8>`_;
|
||||
* **500 Internal Server Error** indicate a server failure `<https://tools.ietf.org/html/rfc7231#section-6.6.1>`_.
|
||||
|
||||
You can find a complete list of HTTP Status at `<https://httpstatuses.com/>`_ or `<https://httpstatuses.io/>`_
|
||||
|
||||
If you get a *500 Internal Server Error*, please report it in the `gCube ticketing system <https://support.d4science.org>`_.
|
||||
|
||||
Please use this checklist before reporting an error:
|
||||
|
||||
* Replicate the request;
|
||||
* The failure could be temporal due to a network error, a server issue, and many other temporal issues. For this reason, please retry the request after a certain amount of time before reporting the issue;
|
||||
* indicate how to replicate the error;
|
||||
* indicate the time when the error occurred (this simplifies identifying the issue).
|
||||
|
||||
HTTP Methods
|
||||
------------
|
||||
|
||||
gCat is a pure RESTful service. It uses standard HTTP Methods to perform a listing of collections and CRUD (Create Read Update Delete) operations on instances.
|
||||
|
||||
|
||||
.. table::
|
||||
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Operation | HTTP Method | URL | Success HTTP Status | Safe | Idempotent |
|
||||
+==============+=============+========================================+=====================+========+============+
|
||||
| Supported | OPTIONS | /{COLLECTION} | 204 No Content | Y | Y |
|
||||
| HTTP Methods | | | [#allow]_ | | |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| List | GET | /{COLLECTION} | 200 OK | Y | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Count | GET | /{COLLECTION}?count=true | 200 OK | Y | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Exists | HEAD | /{COLLECTION} | 204 No Content | Y | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Create | POST | /{COLLECTION} | 201 Created | N | N |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Supported | OPTIONS | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | Y | Y |
|
||||
| HTTP Methods | | | [#allow]_ | | |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Exist | HEAD | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | Y | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Read | GET | /{COLLECTION}/{INSTANCE_ID} | 200 OK | Y | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Update | PUT | /{COLLECTION}/{INSTANCE_ID} | 200 OK | N | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Patch | PATCH | /{COLLECTION}/{INSTANCE_ID} | 200 OK | N | Y |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Delete | DELETE | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | N | N [#del]_ |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| Purge | DELETE | /{COLLECTION}/{INSTANCE_ID}?purge=true | 204 No Content | N | N [#del]_ |
|
||||
+ +-------------+----------------------------------------+---------------------+--------+------------+
|
||||
| | PURGE | /{COLLECTION}/{INSTANCE_ID} | 204 No Content | N | N [#del]_ |
|
||||
+--------------+-------------+----------------------------------------+---------------------+--------+------------+
|
||||
|
||||
.. [#allow] Supported HTTP Methods in **Allow** HTTP Header
|
||||
|
||||
.. [#del] DELETE has been defined as idempotent.
|
||||
|
||||
*Allamaraju* [#Allamaraju]_ argues that DELETE idempotency should be accomplished client-side.
|
||||
The server should inform the client if the delete operation succeeded because the resource was deleted or it was not found, i.e., **404 Not Found** error is suggested instead of **204 No Content**.
|
||||
The latter situation should be treated as idempotent by the client.
|
||||
|
||||
We share the same vision. For this reason, gCat does not provide server-side idempotency for DELETE and PURGE operations.
|
||||
|
||||
.. [#Allamaraju] Allamaraju S. RESTful Web Services Cookbook: Solutions for Improving Scalability and Simplicity. O’Reilly. first ed. 2010
|
||||
|
||||
|
||||
About URL
|
||||
^^^^^^^^^
|
||||
|
||||
The presented URL uses the following convention:
|
||||
|
||||
* **{COLLECTION}** is the plural name of the entity type;
|
||||
* **{INSTANCE_ID}** is an identification that enables univocally identifying the instance in the collection.
|
||||
|
||||
|
||||
About Safety and Idempotency properties
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
* A method is *Safe* if it does not produce any side effects.
|
||||
"This does not prevent an implementation from including behaviour that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method"
|
||||
`<https://tools.ietf.org/html/rfc7231#section-4.2.1>`_;
|
||||
* A method is *Idempotent* if the same operation repeated multiple times has the same side effect as using it one time.
|
||||
"repeating the request will have the same intended effect, even if the original request succeeded, though the response might differ"
|
||||
`<https://tools.ietf.org/html/rfc7231#section-4.2.2>`_.
|
||||
|
||||
You can find more information about HTTP Methods at `<https://restfulapi.net/http-methods/>`_
|
||||
|
||||
Uncommon HTTP Methods
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* PATCH method allows to perform a differential update (i.e. an update which provides only the differences and not the whole new representation);
|
||||
* PURGE method is not a standard but is widely used in services that require this action
|
||||
(e.g. `Varnish <https://varnish-cache.org/docs/3.0/tutorial/purging.html>`_, `Squid <https://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache.3F>`_).
|
||||
gCat provides support for this method, but to support a wider range of clients, it also provides the Purge action via *DELETE* with the additional get parameter ``purge=true``.
|
||||
|
||||
|
||||
Content-Type
|
||||
------------
|
||||
|
||||
Any request must contain an indication of the interesting content type.
|
||||
|
||||
The client must specify the **Accept** HTTP Header for any operation returning a result.
|
||||
|
||||
.. code-block:: rest
|
||||
|
||||
Accept: application/json
|
||||
|
||||
For any operation sending content to the service, it is necessary to specify the **Content-Type** HTTP Header.
|
||||
|
||||
.. code-block:: rest
|
||||
|
||||
Content-Type: application/json
|
||||
|
||||
The service accepts and returns only JSON objects.
|
||||
|
||||
|
||||
|
||||
Collections
|
||||
-----------
|
||||
|
||||
|
||||
|
||||
|
||||
Roles
|
||||
-----
|
||||
|
||||
|
||||
|
||||
Java Client
|
||||
===========
|
||||
|
||||
We provide the following Java Client out-of-the-box.
|
||||
|
||||
.. TIP::
|
||||
If you're coding in Java, it is recommended that you use this Java Client.
|
||||
|
||||
**Maven Coordinates**
|
||||
|
||||
.. code:: xml
|
||||
|
||||
<groupId>org.gcube.service</groupId>
|
||||
<artifactId>helloworld-client</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
|
||||
|
||||
**Methods Result**
|
||||
|
||||
The service exposes `its methods <../api-docs/index.html>`_ using a standard naming approach. Moreover, they accept (in the case of HTTP POST/PUT methods) JSON objects.
|
||||
|
||||
.. IMPORTANT::
|
||||
The result of all methods is always a JSON object as per below:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
....
|
||||
}
|
||||
|
||||
*Inputs are automatically validated before the request is served.*
|
||||
|
||||
|
||||
**Usage examples**
|
||||
|
||||
- Example 1
|
||||
|
||||
.. code:: java
|
||||
|
||||
import org.gcube....;
|
||||
|
||||
|
||||
|
||||
|
||||
Service Discovery on IS
|
||||
=======================
|
||||
|
||||
The service can be discovered in the gCore IS as gCore Endpoint with the following parameter:
|
||||
|
||||
.. code:: xml
|
||||
|
||||
<ServiceClass>org.gcube.service</ServiceClass>
|
||||
<ServiceName>helloworld</ServiceName>
|
||||
|
||||
|
||||
The service can be discovered in the Facet-Based IS as EService with the following JSON query:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"@class": "EService",
|
||||
"consistsOf": [
|
||||
{
|
||||
"@class": "IsIdentifiedBy",
|
||||
"target": {
|
||||
"@class": "SoftwareFacet",
|
||||
"group": "org.gcube.service",
|
||||
"name": "helloworld"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Service Maven Coordinates
|
||||
=========================
|
||||
|
||||
The maven coordinates of the Hello World SG4 service are:
|
||||
|
||||
.. code:: xml
|
||||
|
||||
<groupId>org.gcube.service</groupId>
|
||||
<artifactId>helloworld</artifactId>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
|
@ -0,0 +1,23 @@
|
|||
Dev and Pre Users used for moderation tests
|
||||
========
|
||||
|
||||
To perform moderation tests in dev and preproduction infrastructure we use different users with the indicated roles.
|
||||
|
||||
.. table::
|
||||
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| User | Username | Role |
|
||||
+===============+===============+========================================+
|
||||
| Mister Blonde | mister.blonde | Catalogue-Admin + Catalogue-Moderator |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| Mister Blue | mister.blue | Catalogue-Admin |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| Mister Brown | mister.brown | Catalogue-Moderator |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| Mister Orange | mister.orange | Catalogue-Editor |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| Mister Pink | mister.pink | NO ROLE (means Catalogue-Member) |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
| Mister White | mister.white | Catalogue-Manager |
|
||||
+---------------+---------------+----------------------------------------+
|
||||
|
160
pom.xml
160
pom.xml
|
@ -1,23 +1,49 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-parent</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</parent>
|
||||
<groupId>org.gcube.resource-management</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>Resource Manager</name>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-parent</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</parent>
|
||||
<groupId>org.gcube.resource-management</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>Resource Manager</name>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<organization>
|
||||
<name>gCube System</name>
|
||||
<url>https://www.gcube-system.org/</url>
|
||||
</organization>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>luca.frosini</id>
|
||||
<name>Luca Frosini</name>
|
||||
<email>luca.frosini@isti.cnr.it</email>
|
||||
<url>https://www.isti.cnr.it/en/about/people-detail/141/Frosini_Luca</url>
|
||||
<organization>ISTI-CNR</organization>
|
||||
<organizationUrl>https://www.isti.cnr.it/</organizationUrl>
|
||||
<roles>
|
||||
<role>researcher</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
<timezone>Europe/Rome</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<webappDirectory>${project.basedir}${file.separator}src${file.separator}main${file.separator}webapp${file.separator}WEB-INF</webappDirectory>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<webappDirectory>
|
||||
${project.basedir}${file.separator}src${file.separator}main${file.separator}webapp${file.separator}WEB-INF
|
||||
</webappDirectory>
|
||||
<enunciate.version>2.14.0</enunciate.version>
|
||||
<docker.smartgear.version>4.0.1-SNAPSHOT</docker.smartgear.version>
|
||||
</properties>
|
||||
|
||||
<scm>
|
||||
|
@ -79,7 +105,6 @@
|
|||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>gxHTTP</artifactId>
|
||||
|
@ -93,6 +118,7 @@
|
|||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-smartgears</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Required for Enunciate plugin -->
|
||||
<dependency>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
|
@ -107,10 +133,10 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- END Required for Enunciate plugin -->
|
||||
|
||||
|
@ -130,17 +156,21 @@
|
|||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugins>
|
||||
<!-- Sphinx plugin' -->
|
||||
<plugin>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>sphinx-maven-plugin</artifactId>
|
||||
<version>2.10.0</version>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/docs</outputDirectory>
|
||||
<outputDirectory>
|
||||
${project.build.directory}${file.separator}${project.build.finalName}${file.separator}docs</outputDirectory>
|
||||
<builder>html</builder>
|
||||
<configDirectory>${basedir}/docs</configDirectory>
|
||||
<sourceDirectory>${basedir}/docs</sourceDirectory>
|
||||
<configDirectory>${project.basedir}${file.separator}documentation${file.separator}sphinx</configDirectory>
|
||||
<sourceDirectory>${project.basedir}${file.separator}documentation${file.separator}sphinx</sourceDirectory>
|
||||
<!-- brew install sphinx-doc -->
|
||||
<binaryUrl>
|
||||
file:/opt/homebrew/opt/sphinx-doc/bin/sphinx-build</binaryUrl>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
@ -153,43 +183,51 @@
|
|||
</plugin>
|
||||
|
||||
<!-- Enunciate Maven plugin -->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>com.webcohesion.enunciate</groupId>-->
|
||||
<!-- <artifactId>enunciate-maven-plugin</artifactId>-->
|
||||
<!-- <version>${enunciate.version}</version>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>assemble</id>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>assemble</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<plugin>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-maven-plugin</artifactId>
|
||||
<version>${enunciate.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble</id>
|
||||
<goals>
|
||||
<goal>assemble</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!-- This does not works as expected. We need to use the maven-resources-plugin below
|
||||
<docsDir>${project.build.directory}${file.separator}${project.artifactId}-${project.version}${file.separator}api-docs</docsDir>
|
||||
-->
|
||||
<configFile>${project.basedir}${file.separator}documentation${file.separator}enunciate.xml</configFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Copy Enunciate Documentation from your-application/api-docs into your war -->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-resources-plugin</artifactId>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>copy-enunciate-docs</id>-->
|
||||
<!-- <phase>process-resources</phase>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>copy-resources</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <outputDirectory>target</outputDirectory>-->
|
||||
<!-- <resources>-->
|
||||
<!-- <resource>-->
|
||||
<!-- <targetPath>${project.build.directory}/${project.artifactId}-${project.version}/api-docs</targetPath>-->
|
||||
<!-- <directory>${project.build.directory}/api-docs</directory>-->
|
||||
<!-- <filtering>true</filtering>-->
|
||||
<!-- </resource>-->
|
||||
<!-- </resources>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-enunciate-docs</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>${project.build.directory}${file.separator}${project.artifactId}-${project.version}${file.separator}api-docs</targetPath>
|
||||
<directory>${project.build.directory}/api-docs</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -12,9 +12,9 @@ import jakarta.ws.rs.ApplicationPath;
|
|||
*/
|
||||
@ApplicationPath("/")
|
||||
@ManagedBy(ResourceManager.class)
|
||||
public class ResourceInitializer extends ResourceConfig {
|
||||
public class RMInitializer extends ResourceConfig {
|
||||
|
||||
public ResourceInitializer() {
|
||||
public RMInitializer() {
|
||||
packages(BaseREST.class.getPackage().toString());
|
||||
packages(Configuration.class.getPackage().toString());
|
||||
}
|
|
@ -38,7 +38,8 @@ public class ResourceManager implements ApplicationManager {
|
|||
context);
|
||||
|
||||
ApplicationContext applicationContext = ContextProvider.get();
|
||||
String rrEServiceID = applicationContext.id();
|
||||
String rmEServiceID = applicationContext.id();
|
||||
logger.info("Resource Manager ahs the following ID {}", rmEServiceID);
|
||||
|
||||
|
||||
logger.trace(
|
||||
|
|
|
@ -20,7 +20,7 @@ import jakarta.ws.rs.core.UriInfo;
|
|||
})
|
||||
public class BaseREST {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json;charset=UTF-8";
|
||||
public static final String APPLICATION_JSON_API = "application/vnd.api+json";
|
||||
|
@ -35,11 +35,6 @@ public class BaseREST {
|
|||
|
||||
protected static final String LOCATION_HEADER = "Location";
|
||||
|
||||
protected void setCalledMethod(String method) {
|
||||
InnerMethodName.set(method);
|
||||
logger.info("{}", uriInfo.getAbsolutePath());
|
||||
}
|
||||
|
||||
protected ResponseBuilder addLocation(ResponseBuilder responseBuilder, String id) {
|
||||
return responseBuilder.header(LOCATION_HEADER,
|
||||
String.format("%s/%s", uriInfo.getAbsolutePath().toString(), id));
|
||||
|
@ -55,4 +50,33 @@ public class BaseREST {
|
|||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
protected void setAccountingMethod(String method) {
|
||||
InnerMethodName.set(method);
|
||||
logger.info("{}", uriInfo.getAbsolutePath());
|
||||
}
|
||||
|
||||
// protected void setAccountingMethod(Method method, String type) {
|
||||
// StringBuffer accountingMethod = new StringBuffer();
|
||||
// accountingMethod.append(method.getPrefix());
|
||||
// accountingMethod.append(type);
|
||||
// accountingMethod.append(method.getSuffix());
|
||||
// setAccountingMethod(accountingMethod.toString());
|
||||
// }
|
||||
//
|
||||
// private ServerRequestInfo initRequestInfo(ServerRequestInfo requestInfo) {
|
||||
// requestInfo.setUriInfo(uriInfo);
|
||||
// RequestUtility.getRequestInfo().set(requestInfo);
|
||||
// return requestInfo;
|
||||
// }
|
||||
//
|
||||
// protected ServerRequestInfo initRequestInfo(int offset, int limit) {
|
||||
// ServerRequestInfo requestInfo = new ServerRequestInfo(offset, limit);
|
||||
// return initRequestInfo(requestInfo);
|
||||
// }
|
||||
//
|
||||
// protected ServerRequestInfo initRequestInfo() {
|
||||
// ServerRequestInfo requestInfo = new ServerRequestInfo();
|
||||
// return initRequestInfo(requestInfo);
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package org.gcube.resourcemanagement.rest;
|
||||
|
||||
import org.gcube.informationsystem.contexts.reference.entities.Context;
|
||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException;
|
||||
import org.gcube.informationsystem.resourceregistry.api.rest.ContextPath;
|
||||
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
@Path(ContextManager.CONTEXTS_PATH_PART)
|
||||
public class ContextManager extends BaseREST {
|
||||
|
||||
public static final String CONTEXTS_PATH_PART = "contexts";
|
||||
|
||||
public static final String CONTEXT_UUID_PATH_PARAMETER = "CONTEXT_UUID";
|
||||
|
||||
public static final String CURRENT_CONTEXT_PATH_PART = "CURRENT_CONTEXT";
|
||||
|
||||
public ContextManager() {
|
||||
super();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new Context suing the provided definition
|
||||
*
|
||||
* POST /contexts
|
||||
*
|
||||
* BODY: {...}
|
||||
*
|
||||
*/
|
||||
@POST
|
||||
@Path("{" + ContextManager.CONTEXT_UUID_PATH_PARAMETER + "}")
|
||||
@Consumes({MediaType.TEXT_PLAIN, BaseREST.APPLICATION_JSON_CHARSET_UTF_8})
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
public String create(String json)
|
||||
throws ResourceRegistryException {
|
||||
logger.info("Requested to update/create {} with json {} ", Context.NAME, json);
|
||||
// setAccountingMethod(Method.UPDATE, Context.NAME);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow to read the context definition
|
||||
* GET /contexts/{UUID}
|
||||
* e.g. GET /contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
|
||||
*
|
||||
*/
|
||||
@GET
|
||||
@Path("{" + ContextManager.CONTEXT_UUID_PATH_PARAMETER + "}")
|
||||
@Consumes({MediaType.TEXT_PLAIN, BaseREST.APPLICATION_JSON_CHARSET_UTF_8})
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
public String read(@PathParam(ContextManager.CONTEXT_UUID_PATH_PARAMETER) String uuid)
|
||||
throws ContextNotFoundException, ResourceRegistryException {
|
||||
if(uuid.compareTo(ContextPath.CURRENT_CONTEXT_PATH_PART)==0){
|
||||
//uuid = ContextUtility.getCurrentSecurityContext().getUUID().toString();
|
||||
// TODO get from IS
|
||||
}
|
||||
logger.info("Requested to read {} with id {} ", Context.NAME, uuid);
|
||||
// setAccountingMethod(Method.READ, Context.NAME);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Update an existing Context definition
|
||||
*
|
||||
* PUT /contexts/{UUID}
|
||||
* e.g. PUT /contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
|
||||
*
|
||||
* BODY: {...}
|
||||
*
|
||||
*/
|
||||
@PUT
|
||||
@Path("{" + ContextManager.CONTEXT_UUID_PATH_PARAMETER + "}")
|
||||
@Consumes({MediaType.TEXT_PLAIN, BaseREST.APPLICATION_JSON_CHARSET_UTF_8})
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
public String update(@PathParam(ContextManager.CONTEXT_UUID_PATH_PARAMETER) String uuid, String json)
|
||||
throws ResourceRegistryException {
|
||||
logger.info("Requested to update/create {} with json {} ", Context.NAME, json);
|
||||
// setAccountingMethod(Method.UPDATE, Context.NAME);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* DELETE /contexts/{UUID}
|
||||
* e.g. DELETE /contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
|
||||
*/
|
||||
@DELETE
|
||||
@Consumes({MediaType.TEXT_PLAIN, BaseREST.APPLICATION_JSON_CHARSET_UTF_8})
|
||||
@Path("{" + ContextManager.CONTEXT_UUID_PATH_PARAMETER + "}")
|
||||
public Response delete(@PathParam(ContextManager.CONTEXT_UUID_PATH_PARAMETER) String uuid)
|
||||
throws ContextNotFoundException, ResourceRegistryException {
|
||||
logger.info("Requested to delete {} with id {} ", Context.NAME, uuid);
|
||||
setAccountingMethod("deleteContext");
|
||||
|
||||
return Response.status(Status.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@ import jakarta.ws.rs.ext.Provider;
|
|||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
@Provider
|
||||
public class ResourceManagerExceptionMapper implements ExceptionMapper<Exception> {
|
||||
public class RMExceptionMapper implements ExceptionMapper<Exception> {
|
||||
|
||||
@Override
|
||||
public Response toResponse(Exception exception) {
|
|
@ -32,10 +32,10 @@ import jakarta.ws.rs.core.Response.Status;
|
|||
import jakarta.xml.ws.WebServiceException;
|
||||
|
||||
/**
|
||||
* The catalogue configuration for the context of the request
|
||||
* The Resource Manager configuration for the context of the request
|
||||
* (i.e. the context where the token has been generated).
|
||||
*
|
||||
* Only Catalogue-Managers are able to invoke non-safe methods.
|
||||
* Only Managers are able to invoke non-safe methods.
|
||||
*
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
|
@ -100,18 +100,18 @@ public class Configuration extends BaseREST {
|
|||
}
|
||||
|
||||
/**
|
||||
* This API allows to read the RR configuration for the
|
||||
* This API allows to read the RM configuration for the
|
||||
* current context (i.e. the context where the token has been generated).<br/>
|
||||
*/
|
||||
@GET
|
||||
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_EDITOR, Role.CATALOGUE_ADMIN, Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
|
||||
@StatusCodes ({
|
||||
@ResponseCode(code = 200, condition = "Resource Manager configuration successfully read."),
|
||||
@ResponseCode(code = 401, condition = "Only User with role Manager above can read the configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while reading catalogue configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while reading the configuration."),
|
||||
})
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @return
|
||||
|
@ -153,11 +153,10 @@ public class Configuration extends BaseREST {
|
|||
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
|
||||
@Consumes(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
|
||||
@StatusCodes ({
|
||||
@ResponseCode(code = 200, condition = "Catalogue configuration successfully created/updated."),
|
||||
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can create/update catalogue configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while creating/updating catalogue configuration."),
|
||||
@ResponseCode(code = 200, condition = "Resource Manager configuration successfully created/updated."),
|
||||
@ResponseCode(code = 401, condition = "Only User with role Manager above can create/update the configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while creating/updating the configuration."),
|
||||
})
|
||||
@OperationId("Create or Update")
|
||||
public String createOrUpdate(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context, String json) throws WebServiceException {
|
||||
|
@ -187,7 +186,7 @@ public class Configuration extends BaseREST {
|
|||
}
|
||||
|
||||
/**
|
||||
* This API allows to patch the catalogue configuration for the
|
||||
* This API allows to patch the Resource Manager configuration for the
|
||||
* context of the request (i.e. the context where the token has been generated)
|
||||
* using the json provided as request body.<br/>
|
||||
*/
|
||||
|
@ -195,11 +194,10 @@ public class Configuration extends BaseREST {
|
|||
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
|
||||
@Consumes(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
@Produces(BaseREST.APPLICATION_JSON_CHARSET_UTF_8)
|
||||
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
|
||||
@StatusCodes ({
|
||||
@ResponseCode(code = 200, condition = "Catalogue configuration successfully updated."),
|
||||
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can update catalogue configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while updating catalogue configuration."),
|
||||
@ResponseCode(code = 200, condition = "Resource Manager configuration successfully patched."),
|
||||
@ResponseCode(code = 401, condition = "Only User with role Manager above can patch the configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while patching the configuration."),
|
||||
})
|
||||
public Response patch(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context, String json) throws WebServiceException {
|
||||
try {
|
||||
|
@ -233,11 +231,11 @@ public class Configuration extends BaseREST {
|
|||
* context of the request (i.e. the context where the token has been generated).<br/>
|
||||
*
|
||||
* This API forces the service to read again from the Information System (IS)
|
||||
* the resource manager configuration for the context of the request.<br/>
|
||||
* the Resource Manager configuration for the context of the request.<br/>
|
||||
*
|
||||
* If the user specifies the <code>purge</code> query parameter this API
|
||||
* remove the configuration from the IS. Please note that this implies that
|
||||
* the resource manager is no more configured for the context of the request.
|
||||
* the Resource Manager is no more configured for the context of the request.
|
||||
*
|
||||
*
|
||||
* @param context context must contains the context of the request
|
||||
|
@ -253,9 +251,9 @@ public class Configuration extends BaseREST {
|
|||
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
|
||||
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
|
||||
@StatusCodes ({
|
||||
@ResponseCode(code = 200, condition = "Catalogue configuration successfully deleted."),
|
||||
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can delete catalogue configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while deleting catalogue configuration."),
|
||||
@ResponseCode(code = 200, condition = "Resource Manager configuration successfully deleted."),
|
||||
@ResponseCode(code = 401, condition = "Only User with role Manager above can delete the configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while deleting the configuration."),
|
||||
})
|
||||
public Response delete(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context,
|
||||
@QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) throws WebServiceException {
|
||||
|
@ -304,9 +302,9 @@ public class Configuration extends BaseREST {
|
|||
@Path("/{" + CONTEXT_FULLNAME_PARAMETER + "}")
|
||||
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
|
||||
@StatusCodes ({
|
||||
@ResponseCode(code = 200, condition = "Catalogue configuration successfully deleted."),
|
||||
@ResponseCode(code = 401, condition = "Only Catalogue-Managers can delete catalogue configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while deleting catalogue configuration."),
|
||||
@ResponseCode(code = 200, condition = "Resource Manager configuration purged deleted."),
|
||||
@ResponseCode(code = 401, condition = "Only User with role Manager above can purge the configuration."),
|
||||
@ResponseCode(code = 500, condition = "Error while purging the configuration."),
|
||||
})
|
||||
public Response purge(@PathParam(CONTEXT_FULLNAME_PARAMETER) String context) throws WebServiceException {
|
||||
try {
|
||||
|
|
|
@ -3,20 +3,19 @@
|
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
|
||||
version="4.0">
|
||||
<display-name>Hello World</display-name>
|
||||
<description>
|
||||
A gcube HelloWorld service - smartgears 4
|
||||
</description>
|
||||
<servlet>
|
||||
<servlet-name>HelloWorld</servlet-name>
|
||||
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>jersey.config.server.provider.packages</param-name>
|
||||
<param-value>org.gcube.service.helloworld.services</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>HelloWorld</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<servlet-name>org.gcube.resourcemanagement.RMInitializer</servlet-name>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/docs/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/api-docs/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>org.gcube.resourcemanagement.RMInitializer</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
Loading…
Reference in New Issue