Adding Capif invoker 00/11100/1
authorychacon <yennifer.chacon@est.tech>
Mon, 15 May 2023 09:07:32 +0000 (11:07 +0200)
committerychacon <yennifer.chacon@est.tech>
Mon, 15 May 2023 09:07:32 +0000 (11:07 +0200)
Issue-ID: NONRTRIC-861
Signed-off-by: ychacon <yennifer.chacon@est.tech>
Change-Id: Idccd804e484fa0131496a8d7362bd242bf282a16

30 files changed:
invoker/generate.sh [new file with mode: 0755]
invoker/go.mod [new file with mode: 0644]
invoker/go.sum [new file with mode: 0644]
invoker/gogeneratorspecs/common/generator_settings.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/common29122/generator_settings.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/common29571/generator_settings.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml [new file with mode: 0644]
invoker/gogeneratorspecs/securityapi/generator_settings_types.yaml [new file with mode: 0644]
invoker/handler/common_handler.go [new file with mode: 0644]
invoker/handler/discovery_handler.go [new file with mode: 0644]
invoker/handler/gettoken_handler.go [new file with mode: 0644]
invoker/handler/home_handler.go [new file with mode: 0644]
invoker/handler/offboardinvoker_handler.go [new file with mode: 0644]
invoker/handler/onboardinvoker_handler.go [new file with mode: 0644]
invoker/handler/securitymethod_handler.go [new file with mode: 0644]
invoker/internal/gentools/commoncollector/commoncollector.go [new file with mode: 0644]
invoker/internal/gentools/enumfixer/enumfixer.go [new file with mode: 0644]
invoker/internal/gentools/specificationfixer/specificationfixer.go [new file with mode: 0644]
invoker/main.go [new file with mode: 0644]
invoker/view/base.html [new file with mode: 0644]
invoker/view/css/style.css [new file with mode: 0644]
invoker/view/discovery.html [new file with mode: 0644]
invoker/view/gettoken.html [new file with mode: 0644]
invoker/view/home.html [new file with mode: 0644]
invoker/view/js/script.js [new file with mode: 0644]
invoker/view/onboardinvoker.html [new file with mode: 0644]
invoker/view/securitymethod.html [new file with mode: 0644]

diff --git a/invoker/generate.sh b/invoker/generate.sh
new file mode 100755 (executable)
index 0000000..18a4f5b
--- /dev/null
@@ -0,0 +1,168 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+cwd=$(pwd)
+
+mkdir -p specs
+
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.222/29222-h60.zip -o specs/apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.122/29122-h70.zip -o specs/common29122apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.508/29508-h80.zip -o specs/common29508apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.510/29510-h70.zip -o specs/common29510apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.512/29512-h80.zip -o specs/common29512apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.514/29514-h60.zip -o specs/common29514apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.517/29517-h70.zip -o specs/common29517apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.518/29518-h70.zip -o specs/common29518apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.522/29522-h70.zip -o specs/common29522apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.523/29523-h80.zip -o specs/common29523apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.554/29554-h40.zip -o specs/common29554apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.571/29571-h70.zip -o specs/common29571apidef.zip
+curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.572/29572-h60.zip -o specs/common29572apidef.zip
+
+cd specs/
+
+jar xvf apidef.zip
+jar xvf common29122apidef.zip
+jar xvf common29508apidef.zip
+jar xvf common29510apidef.zip
+jar xvf common29512apidef.zip
+jar xvf common29514apidef.zip
+jar xvf common29517apidef.zip
+jar xvf common29518apidef.zip
+jar xvf common29522apidef.zip
+jar xvf common29523apidef.zip
+jar xvf common29554apidef.zip
+jar xvf common29571apidef.zip
+jar xvf common29572apidef.zip
+
+# Remove types that are not used by CAPIF that have dependencies to other specifications.
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\CivicAddress/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\ExternalMbsServiceArea/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\GeographicArea/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\GeoServiceArea/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsMediaComp/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsMediaCompRm/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsMediaInfo/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsServiceInfo/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsSession/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\SpatialValidityCond/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+
+# Remove attributes that can not be generated easily.
+sed '/accessTokenError.*/,+3d' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+sed '/accessTokenRequest.*/,+3d' TS29571_CommonData.yaml >temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+
+
+sed '/oneOf.*/,+2d' TS29222_CAPIF_Publish_Service_API.yaml >temp.yaml
+mv temp.yaml TS29222_CAPIF_Publish_Service_API.yaml
+
+# Replace references to external specs that are collected to the common spec by the commoncollector
+# <replacements_start>
+cat TS29122_CommonData.yaml | sed 's/TS29572_Nlmf_Location/CommonData/g' > temp.yaml
+mv temp.yaml TS29122_CommonData.yaml
+cat TS29122_CommonData.yaml | sed 's/TS29554_Npcf_BDTPolicyControl/CommonData/g' > temp.yaml
+mv temp.yaml TS29122_CommonData.yaml
+cat TS29122_CommonData.yaml | sed 's/TS29514_Npcf_PolicyAuthorization/CommonData/g' > temp.yaml
+mv temp.yaml TS29122_CommonData.yaml
+cat TS29571_CommonData.yaml | sed 's/TS29514_Npcf_PolicyAuthorization/CommonData/g' > temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+cat TS29571_CommonData.yaml | sed 's/TS29572_Nlmf_Location/CommonData/g' > temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+cat TS29222_CAPIF_Publish_Service_API.yaml | sed 's/TS29572_Nlmf_Location/CommonData/g' > temp.yaml
+mv temp.yaml TS29222_CAPIF_Publish_Service_API.yaml
+# <new_replacement>
+
+# This spec has references to itself that need to be removed
+cat TS29571_CommonData.yaml | sed 's/TS29571_CommonData.yaml//g' > temp.yaml
+mv temp.yaml TS29571_CommonData.yaml
+
+cd $cwd
+
+echo "Fixing enums"
+cd internal/gentools/enumfixer
+go build .
+./enumfixer -apidir=../../../specs
+
+cd $cwd
+echo "Gathering common references"
+cd internal/gentools/commoncollector
+go build .
+./commoncollector -apidir=../../../specs
+
+cd $cwd
+echo "Fixing misc in specifications"
+cd internal/gentools/specificationfixer
+go build .
+./specificationfixer -apidir=../../../specs
+
+cd $cwd
+
+go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.10.1
+PATH=$PATH:~/go/bin
+
+echo "Generating TS29122_CommonData"
+mkdir -p internal/common29122
+oapi-codegen --config gogeneratorspecs/common29122/generator_settings.yaml specs/TS29122_CommonData.yaml
+
+echo "Generating aggregated CommonData"
+mkdir -p internal/common
+oapi-codegen --config gogeneratorspecs/common/generator_settings.yaml specs/CommonData.yaml
+
+echo "Generating TS29571_CommonData"
+mkdir -p internal/common29571
+oapi-codegen --config gogeneratorspecs/common29571/generator_settings.yaml specs/TS29571_CommonData.yaml
+
+
+echo "Generating TS29222_CAPIF_API_Provider_Management_API"
+mkdir -p internal/providermanagementapi
+oapi-codegen --config gogeneratorspecs/providermanagementapi/generator_settings_types.yaml specs/TS29222_CAPIF_API_Provider_Management_API.yaml
+
+echo "Generating TS29222_CAPIF_Publish_Service_API"
+mkdir -p internal/publishserviceapi
+oapi-codegen --config gogeneratorspecs/publishserviceapi/generator_settings_types.yaml specs/TS29222_CAPIF_Publish_Service_API.yaml
+
+echo "Generating TS29222_CAPIF_API_Invoker_Management_API"
+mkdir -p internal/invokermanagementapi
+oapi-codegen --config gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
+
+echo "Generating TS29222_CAPIF_Discover_Service_API"
+mkdir -p internal/discoverserviceapi
+oapi-codegen --config gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml specs/TS29222_CAPIF_Discover_Service_API.yaml
+
+echo "Generating TS29222_CAPIF_Security_API"
+mkdir -p internal/securityapi
+oapi-codegen --config gogeneratorspecs/securityapi/generator_settings_types.yaml specs/TS29222_CAPIF_Security_API.yaml
+
+echo "Cleanup"
+rm -rf specs
+
+echo "Generating mocks."
+go generate ./...
\ No newline at end of file
diff --git a/invoker/go.mod b/invoker/go.mod
new file mode 100644 (file)
index 0000000..b38e295
--- /dev/null
@@ -0,0 +1,35 @@
+module oransc.org/nonrtric/capifinvoker
+
+go 1.19
+
+require (
+       github.com/deepmap/oapi-codegen v1.12.4
+       github.com/getkin/kin-openapi v0.116.0
+       github.com/labstack/echo/v4 v4.10.2
+       github.com/sirupsen/logrus v1.9.0
+)
+
+require (
+       github.com/go-openapi/jsonpointer v0.19.5 // indirect
+       github.com/go-openapi/swag v0.21.1 // indirect
+       github.com/google/uuid v1.3.0 // indirect
+       github.com/invopop/yaml v0.1.0 // indirect
+       github.com/josharian/intern v1.0.0 // indirect
+       github.com/mailru/easyjson v0.7.7 // indirect
+       github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+       github.com/perimeterx/marshmallow v1.1.4 // indirect
+       gopkg.in/yaml.v2 v2.4.0
+       gopkg.in/yaml.v3 v3.0.1 // indirect
+)
+
+require (
+       github.com/labstack/gommon v0.4.0
+       github.com/mattn/go-colorable v0.1.13 // indirect
+       github.com/mattn/go-isatty v0.0.17 // indirect
+       github.com/valyala/bytebufferpool v1.0.0 // indirect
+       github.com/valyala/fasttemplate v1.2.2 // indirect
+       golang.org/x/crypto v0.6.0 // indirect
+       golang.org/x/net v0.7.0 // indirect
+       golang.org/x/sys v0.5.0 // indirect
+       golang.org/x/text v0.7.0 // indirect
+)
diff --git a/invoker/go.sum b/invoker/go.sum
new file mode 100644 (file)
index 0000000..cc5ae0e
--- /dev/null
@@ -0,0 +1,98 @@
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
+github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
+github.com/getkin/kin-openapi v0.116.0 h1:o986hwgMzR972JzOG5j6+WTwWqllZLs1EJKMKCivs2E=
+github.com/getkin/kin-openapi v0.116.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
+github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
+github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
+github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
+github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
+github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
+github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
+github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
+github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
+github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
+golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/invoker/gogeneratorspecs/common/generator_settings.yaml b/invoker/gogeneratorspecs/common/generator_settings.yaml
new file mode 100644 (file)
index 0000000..298e588
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common/common.gen.go
+package: common
+generate:
+  - types
+  - skip-prune
+  - spec
+import-mapping:
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
diff --git a/invoker/gogeneratorspecs/common29122/generator_settings.yaml b/invoker/gogeneratorspecs/common29122/generator_settings.yaml
new file mode 100644 (file)
index 0000000..7470a73
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2022: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common29122/common29122.gen.go
+package: common29122
+generate:
+  - types
+  - skip-prune
+  - spec
+import-mapping:
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/common29571/generator_settings.yaml b/invoker/gogeneratorspecs/common29571/generator_settings.yaml
new file mode 100644 (file)
index 0000000..8401e8d
--- /dev/null
@@ -0,0 +1,27 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2022: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common29571/common29571.gen.go
+package: common29571
+generate:
+  - types
+  - skip-prune
+  - spec
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml b/invoker/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..1c61f4a
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/discoverserviceapi/discoverserviceapi-types.gen.go
+package: discoverserviceapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/capifinvoker/internal/publishserviceapi
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml b/invoker/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..4f994fd
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/invokermanagementapi/invokermanagementapi-types.gen.go
+package: invokermanagementapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/capifinvoker/internal/publishserviceapi
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml b/invoker/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..f1fae3a
--- /dev/null
@@ -0,0 +1,28 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/providermanagementapi/providermanagementapi-types.gen.go
+package: providermanagementapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml b/invoker/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..2a05fb8
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/publishserviceapi/publishserviceapi-types.gen.go
+package: publishserviceapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common
\ No newline at end of file
diff --git a/invoker/gogeneratorspecs/securityapi/generator_settings_types.yaml b/invoker/gogeneratorspecs/securityapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..5c1a873
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023: Nordix Foundation
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/securityapi/securityapi-types.gen.go
+package: securityapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/capifinvoker/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/capifinvoker/internal/publishserviceapi
\ No newline at end of file
diff --git a/invoker/handler/common_handler.go b/invoker/handler/common_handler.go
new file mode 100644 (file)
index 0000000..081fa94
--- /dev/null
@@ -0,0 +1,79 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "fmt"
+       "io"
+       "net/http"
+)
+
+func makeRequest(method, url string, headers map[string]string, data io.Reader) ([]byte, error) {
+       client := &http.Client{}
+
+       // Create a new HTTP request with the specified method and URL
+       req, err := http.NewRequest(method, url, nil)
+       if err != nil {
+               return nil, err
+       }
+
+       // Set any headers specified in the headers map
+       for k, v := range headers {
+               req.Header.Set(k, v)
+       }
+
+       // If there is data to send, marshal it to JSON and set it as the request body
+       if data != nil {
+               /*jsonBytes, err := json.Marshal(data)
+               if err != nil {
+                       return nil, err
+               }*/
+               req.Body = io.NopCloser(data)
+       }
+
+       // Send the request and get the response
+       if resp, err := client.Do(req); err == nil {
+               if isResponseSuccess(resp.StatusCode) {
+                       defer resp.Body.Close()
+
+                       // Read the response body
+                       respBody, err := io.ReadAll(resp.Body)
+                       if err != nil {
+                               return nil, err
+                       }
+                       return respBody, nil
+               } else {
+                       return nil, getRequestError(resp)
+               }
+       } else {
+               return nil, err
+       }
+}
+
+func isResponseSuccess(statusCode int) bool {
+       return statusCode >= http.StatusOK && statusCode <= 299
+}
+
+func getRequestError(response *http.Response) error {
+       defer response.Body.Close()
+       responseData, _ := io.ReadAll(response.Body)
+
+       return fmt.Errorf("message:  %v code: %v", string(responseData), response.StatusCode)
+}
diff --git a/invoker/handler/discovery_handler.go b/invoker/handler/discovery_handler.go
new file mode 100644 (file)
index 0000000..f15ddc5
--- /dev/null
@@ -0,0 +1,99 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "encoding/json"
+       "fmt"
+       "net/http"
+       "net/url"
+
+       "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+       "oransc.org/nonrtric/capifinvoker/internal/discoverserviceapi"
+)
+
+func DiscoverAPIs(server string) echo.HandlerFunc {
+       return func(c echo.Context) error {
+
+               invokerId := c.FormValue("api-invoker-id")
+               if invokerId == "" {
+                       return c.Render(http.StatusOK, "discovery.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    false,
+                       })
+               }
+
+               //server format: http://localhost:8090
+               urlStr, _ := url.Parse(server + "/service-apis/v1/allServiceAPIs")
+               log.Infof("[Discovery API] apis to %v for invokerId: %v", urlStr, invokerId)
+
+               //TODO check how to remove empty parameters
+               c.Request().ParseForm()
+               params := c.Request().Form
+               for key, val := range params {
+                       if len(val) == 0 || val[0] == "" {
+                               params.Del(key)
+                       }
+               }
+               urlStr.RawQuery = params.Encode()
+
+               headers := map[string]string{
+                       "Content-Type": "text/plain",
+               }
+               resp, err := makeRequest("GET", urlStr.String(), headers, nil)
+               if err != nil {
+                       log.Errorf("[Discovery API] %v", fmt.Sprintf("error: %v", err))
+                       return c.Render(http.StatusBadRequest, "discovery.html", map[string]interface{}{
+                               "response":   fmt.Sprintf("error: %v", err),
+                               "isError":    true,
+                               "isResponse": false,
+                       })
+               }
+               log.Infof("[Discovery API] Response from service: %+v error: %v\n", string(resp), err)
+
+               var resAPIs discoverserviceapi.DiscoveredAPIs
+               err = json.Unmarshal(resp, &resAPIs)
+               if err != nil {
+                       log.Error("[Discovery API] error unmarshaling parameter DiscoveredAPIs as JSON")
+                       return c.Render(http.StatusBadRequest, "discovery.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "error unmarshaling parameter []DiscoveredAPIs as JSON",
+                       })
+               }
+
+               if len(*resAPIs.ServiceAPIDescriptions) == 0 {
+                       log.Info("[Discovery API] There are no APIs availables for the specified parameters.")
+                       return c.Render(http.StatusOK, "discovery.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    false,
+                               "isEmpty":    true,
+                               "response":   "There are no APIs availables for the specified parameters.",
+                       })
+               }
+
+               bytes, _ := json.Marshal(resAPIs)
+               return c.Render(http.StatusOK, "discovery.html", map[string]interface{}{
+                       "isResponse": true,
+                       "response":   string(bytes),
+               })
+       }
+}
diff --git a/invoker/handler/gettoken_handler.go b/invoker/handler/gettoken_handler.go
new file mode 100644 (file)
index 0000000..625840f
--- /dev/null
@@ -0,0 +1,100 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "encoding/json"
+       "fmt"
+       "net/http"
+       "net/url"
+       "strconv"
+       "strings"
+
+       "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+       "oransc.org/nonrtric/capifinvoker/internal/securityapi"
+)
+
+func GetTokenHandler(c echo.Context) error {
+       log.Info("[Security API] in get token handler")
+       return c.Render(http.StatusOK, "gettoken.html", map[string]interface{}{
+               "isError":    false,
+               "isResponse": false,
+       })
+}
+
+func ObtainToken(server string) echo.HandlerFunc {
+       return func(c echo.Context) error {
+               log.Info("[Security API] in ObtainToken")
+               securityId := c.FormValue("securityId")
+               if securityId == "" {
+                       log.Error("[Security API] field securityId is needed")
+                       return c.Render(http.StatusBadRequest, "gettoken.html", map[string]interface{}{
+                               "isError":    true,
+                               "isResponse": false,
+                               "response":   "field securityId is needed",
+                       })
+               }
+
+               //server format: http://localhost:8090
+               urlStr := server + "/capif-security/v1/securities/" + securityId + "/token"
+
+               log.Infof("[Security API] url to capif core %v for securityId: %v", urlStr, securityId)
+
+               data := url.Values{}
+               data.Set("client_id", c.FormValue("clientId"))
+               data.Set("client_secret", c.FormValue("clientSecret"))
+               data.Set("grant_type", "client_credentials")
+               data.Set("scope", c.FormValue("scope"))
+
+               headers := map[string]string{
+                       "Content-Type":   "application/x-www-form-urlencoded",
+                       "Content-Length": strconv.Itoa(len(data.Encode())),
+               }
+               resp, err := makeRequest("POST", urlStr, headers, strings.NewReader(data.Encode()))
+               if err != nil {
+                       log.Errorf("[Security API] %v", fmt.Sprintf("error: %v", err))
+                       return c.Render(http.StatusBadRequest, "gettoken.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   fmt.Sprintf("error: %v", err),
+                       })
+               }
+
+               var resToken securityapi.AccessTokenRsp
+               if err = json.Unmarshal(resp, &resToken); err != nil {
+                       log.Error("[Security API] error unmarshaling parameter AccessTokenRsp as JSON")
+                       return c.Render(http.StatusBadRequest, "gettoken.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "Error unmarshaling parameter AccessTokenRsp as JSON",
+                       })
+               }
+
+               // Return the rendered response HTML
+               bytes, _ := json.Marshal(resToken)
+               log.Infof("[Security API] jwt token fetch AccessTokenRsp is %v\n", resToken)
+               return c.Render(http.StatusOK, "gettoken.html", map[string]interface{}{
+                       "isResponse": true,
+                       "isError":    false,
+                       "response":   string(bytes),
+               })
+       }
+}
diff --git a/invoker/handler/home_handler.go b/invoker/handler/home_handler.go
new file mode 100644 (file)
index 0000000..619d624
--- /dev/null
@@ -0,0 +1,32 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "net/http"
+
+       "github.com/labstack/echo/v4"
+)
+
+func HomeHandler(c echo.Context) error {
+       return c.Render(http.StatusOK, "home.html", map[string]interface{}{
+               "name": "HOME",
+       })
+}
diff --git a/invoker/handler/offboardinvoker_handler.go b/invoker/handler/offboardinvoker_handler.go
new file mode 100644 (file)
index 0000000..ad153a4
--- /dev/null
@@ -0,0 +1,20 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
diff --git a/invoker/handler/onboardinvoker_handler.go b/invoker/handler/onboardinvoker_handler.go
new file mode 100644 (file)
index 0000000..5001c9c
--- /dev/null
@@ -0,0 +1,100 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "bytes"
+       "encoding/json"
+       "fmt"
+       "net/http"
+
+       "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+       invokerapi "oransc.org/nonrtric/capifinvoker/internal/invokermanagementapi"
+)
+
+func OnboardingInvokerHandler(c echo.Context) error {
+       return c.Render(http.StatusOK, "onboardinvoker.html", map[string]interface{}{
+               "isError":    false,
+               "isResponse": false,
+       })
+}
+
+func OnboardInvoker(server string) echo.HandlerFunc {
+       return func(c echo.Context) error {
+
+               url := server + "/api-invoker-management/v1/onboardedInvokers"
+               log.Infof("[Register invoker] url to capif core %v\n", url)
+
+               var newInvoker invokerapi.APIInvokerEnrolmentDetails
+               fmt.Printf("Getting enrolment details from UI:: %+v", c.FormValue("enrolmentDetails"))
+               err := json.Unmarshal([]byte(c.FormValue("enrolmentDetails")), &newInvoker)
+               if err != nil {
+                       fmt.Printf("error: %+v", err)
+                       log.Error("[Register invoker] error unmarshaling parameter enrolmentDetails as JSON")
+                       return c.Render(http.StatusBadRequest, "onboardinvoker.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "Error unmarshaling parameter enrolmentDetails as JSON",
+                       })
+               }
+
+               headers := map[string]string{
+                       "Content-Type": "application/json",
+               }
+               jsonBytes, err := json.Marshal(newInvoker)
+               if err != nil {
+                       return c.Render(http.StatusBadRequest, "onboardinvoker.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "Error marshaling parameter enrolmentDetails before doing request",
+                       })
+               }
+
+               resp, err := makeRequest("POST", url, headers, bytes.NewReader(jsonBytes))
+               if err != nil {
+                       log.Errorf("[Register invoker] %v", fmt.Sprintf("error: %v", err))
+                       return c.Render(http.StatusBadRequest, "onboardinvoker.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   fmt.Sprintf("error: %v", err),
+                       })
+               }
+
+               var resInvoker invokerapi.APIInvokerEnrolmentDetails
+               err = json.Unmarshal(resp, &resInvoker)
+               if err != nil {
+                       log.Error("[Register invoker] error unmarshaling response enrolmentDetails as JSON")
+                       return c.Render(http.StatusBadRequest, "onboardinvoker.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "error unmarshaling parameter enrolmentDetails as JSON",
+                       })
+               }
+
+               bytes, _ := json.Marshal(resInvoker)
+               log.Infof("[Register invoker] new invoker register with id %v\n", *resInvoker.ApiInvokerId)
+               return c.Render(http.StatusOK, "onboardinvoker.html", map[string]interface{}{
+                       "isResponse": true,
+                       "isError":    false,
+                       "response":   string(bytes),
+               })
+       }
+}
diff --git a/invoker/handler/securitymethod_handler.go b/invoker/handler/securitymethod_handler.go
new file mode 100644 (file)
index 0000000..7aa4f1b
--- /dev/null
@@ -0,0 +1,109 @@
+// -
+//
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2023: Nordix Foundation
+//     %%
+//     Licensed under the Apache License, Version 2.0 (the "License");
+//     you may not use this file except in compliance with the License.
+//     You may obtain a copy of the License at
+//
+//          http://www.apache.org/licenses/LICENSE-2.0
+//
+//     Unless required by applicable law or agreed to in writing, software
+//     distributed under the License is distributed on an "AS IS" BASIS,
+//     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//     See the License for the specific language governing permissions and
+//     limitations under the License.
+//     ========================LICENSE_END===================================
+package handler
+
+import (
+       "bytes"
+       "encoding/json"
+       "fmt"
+       "net/http"
+
+       "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+       "oransc.org/nonrtric/capifinvoker/internal/securityapi"
+)
+
+func SecurityMethodHandler(c echo.Context) error {
+       log.Info("[Security API] in security method handler")
+       return c.Render(http.StatusOK, "securitymethod.html", map[string]interface{}{
+               "isError":    false,
+               "isResponse": false,
+       })
+}
+
+func ObtainSecurityMethod(server string) echo.HandlerFunc {
+       return func(c echo.Context) error {
+               log.Info("[Security API] in ObtainSecurityMethod")
+               invokerId := c.FormValue("invokerId")
+               if invokerId == "" {
+                       log.Error("[Security API] field invokerId is needed")
+                       return c.Render(http.StatusBadRequest, "securitymethod.html", map[string]interface{}{
+                               "isError":    true,
+                               "isResponse": false,
+                               "response":   "field invokerId is needed",
+                       })
+               }
+
+               //server format: http://localhost:8090
+               url := server + "/capif-security/v1/trustedInvokers/" + invokerId
+
+               log.Infof("[Security API] url to capif core %v for invokerId: %v", url, invokerId)
+               var servSecurity securityapi.ServiceSecurity
+
+               err := json.Unmarshal([]byte(c.FormValue("servSecurity")), &servSecurity)
+               if err != nil {
+                       log.Error("[Security API] error unmarshaling parameter ServiceSecurity as JSON")
+                       return c.Render(http.StatusBadRequest, "securitymethod.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "error unmarshaling parameter ServiceSecurity as JSON",
+                       })
+               }
+
+               headers := map[string]string{
+                       "Content-Type": "application/json",
+               }
+               jsonBytes, err := json.Marshal(servSecurity)
+               if err != nil {
+                       return c.Render(http.StatusBadRequest, "securitymethod.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "Error marshaling parameter ServiceSecurity before doing request",
+                       })
+               }
+               resp, err := makeRequest("PUT", url, headers, bytes.NewReader(jsonBytes))
+               if err != nil {
+                       log.Errorf("[Security API] %v", fmt.Sprintf("error: %v", err))
+                       return c.Render(http.StatusBadRequest, "securitymethod.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   fmt.Sprintf("error: %v", err),
+                       })
+               }
+
+               var resAPI securityapi.ServiceSecurity
+               err = json.Unmarshal(resp, &resAPI)
+               if err != nil {
+                       log.Error("[Security API] error unmarshaling parameter ServiceSecurity as JSON")
+                       return c.Render(http.StatusBadRequest, "securitymethod.html", map[string]interface{}{
+                               "isResponse": false,
+                               "isError":    true,
+                               "response":   "Error unmarshaling parameter ServiceSecurity as JSON",
+                       })
+               }
+
+               // Return the rendered response HTML
+               bytes, _ := json.Marshal(resAPI)
+               return c.Render(http.StatusOK, "securitymethod.html", map[string]interface{}{
+                       "isResponse": true,
+                       "response":   string(bytes),
+               })
+       }
+}
diff --git a/invoker/internal/gentools/commoncollector/commoncollector.go b/invoker/internal/gentools/commoncollector/commoncollector.go
new file mode 100644 (file)
index 0000000..ab85e0a
--- /dev/null
@@ -0,0 +1,119 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2022: Nordix Foundation
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "bufio"
+       "flag"
+       "io/ioutil"
+       "log"
+       "os"
+       "strings"
+
+       "gopkg.in/yaml.v2"
+)
+
+var apiDir *string
+var common = map[interface{}]interface{}{
+       "openapi": "3.0.0",
+       "info": map[interface{}]interface{}{
+               "title":   "Common",
+               "version": "1.0.0",
+       },
+       "components": map[interface{}]interface{}{
+               "schemas": map[interface{}]interface{}{},
+       },
+}
+
+func main() {
+       apiDir = flag.String("apidir", "", "Directory containing API definitions to fix")
+       flag.Parse()
+
+       file, err := os.Open("definitions.txt")
+       if err != nil {
+               log.Fatalf("Error opening file: %v", err)
+       }
+       defer func(file *os.File) {
+               _ = file.Close()
+       }(file)
+
+       scanner := bufio.NewScanner(file)
+       components := common["components"]
+       cMap := components.(map[interface{}]interface{})
+       schemas := cMap["schemas"].(map[interface{}]interface{})
+       for scanner.Scan() {
+               name, data := getDependency(scanner.Text())
+               if name == "EthFlowDescription" {
+                       changeToLocalReference("fDir", "FlowDirection", data)
+               }
+               if name == "ReportingInformation" {
+                       changeToLocalReference("notifMethod", "NotificationMethod", data)
+               }
+               if name == "RelativeCartesianLocation" {
+                       properties := data["properties"].(map[interface{}]interface{})
+                       delete(properties, true)
+                       data["required"] = remove(data["required"].([]interface{}), 1)
+               }
+               schemas[name] = data
+       }
+
+       if err := scanner.Err(); err != nil {
+               log.Fatal(err)
+       }
+
+       modCommon, err := yaml.Marshal(common)
+       if err != nil {
+               log.Fatalf("Marshal: #%v ", err)
+       }
+       err = ioutil.WriteFile(*apiDir+"/"+"CommonData.yaml", modCommon, 0644)
+       if err != nil {
+               log.Fatalf("Error writing yamlFile. #%v ", err)
+       }
+}
+
+func changeToLocalReference(attrname, refName string, data map[interface{}]interface{}) {
+       properties := data["properties"].(map[interface{}]interface{})
+       ref := properties[attrname].(map[interface{}]interface{})
+       ref["$ref"] = "#/components/schemas/" + refName
+}
+
+func getDependency(s string) (string, map[interface{}]interface{}) {
+       info := strings.Split(s, "#")
+       yamlFile, err := ioutil.ReadFile(*apiDir + "/" + info[0])
+       if err != nil {
+               log.Fatalf("Error reading yamlFile. #%v ", err)
+       }
+       m := make(map[string]interface{})
+       err = yaml.Unmarshal(yamlFile, m)
+       if err != nil {
+               log.Fatalf("Unmarshal: %v", err)
+       }
+       components := m["components"]
+       cMap := components.(map[interface{}]interface{})
+       schemas := cMap["schemas"].(map[interface{}]interface{})
+       component := strings.Split(info[1], "/")
+       dep := schemas[component[3]].(map[interface{}]interface{})
+       return component[3], dep
+}
+
+func remove(slice []interface{}, s int) []interface{} {
+       return append(slice[:s], slice[s+1:]...)
+}
diff --git a/invoker/internal/gentools/enumfixer/enumfixer.go b/invoker/internal/gentools/enumfixer/enumfixer.go
new file mode 100644 (file)
index 0000000..e722875
--- /dev/null
@@ -0,0 +1,117 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2022: Nordix Foundation
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "flag"
+       "fmt"
+       "io/ioutil"
+       "log"
+       "os"
+       "path/filepath"
+       "reflect"
+       "strconv"
+       "strings"
+
+       "gopkg.in/yaml.v2"
+)
+
+type Enum struct {
+       Enum        []string `yaml:"enum"`
+       Type        string   `yaml:"type"`
+       Description string   `yaml:"description"`
+}
+
+func main() {
+       var apiDir = flag.String("apidir", "", "Directory containing API definitions to fix")
+       flag.Parse()
+       err := filepath.Walk(*apiDir, fixEnums)
+       if err != nil {
+               fmt.Println(err)
+       }
+}
+
+func fixEnums(path string, info os.FileInfo, _ error) error {
+       if !info.IsDir() && strings.HasSuffix(info.Name(), ".yaml") {
+               yamlFile, err := ioutil.ReadFile(path)
+               if err != nil {
+                       log.Printf("yamlFile. Get err   #%v ", err)
+               }
+               m := make(map[string]interface{})
+               err = yaml.Unmarshal(yamlFile, m)
+               if err != nil {
+                       log.Fatalf("Unmarshal: %v", err)
+               }
+               components := m["components"]
+               if components != nil {
+                       cMap := components.(map[interface{}]interface{})
+                       if _, ok := cMap["schemas"].(map[interface{}]interface{}); ok {
+                               schemas := cMap["schemas"].(map[interface{}]interface{})
+                               for typeName, typeDef := range schemas {
+                                       tDMap := typeDef.(map[interface{}]interface{})
+                                       anyOf, ok := tDMap["anyOf"]
+                                       if ok {
+                                               aOSlice := anyOf.([]interface{})
+                                               correctEnum := Enum{}
+                                               mapInterface := aOSlice[0].(map[interface{}]interface{})
+                                               enumInterface := mapInterface["enum"]
+                                               if enumInterface != nil {
+                                                       is := enumInterface.([]interface{})
+                                                       var enumVals []string
+                                                       for i := 0; i < len(is); i++ {
+                                                               if reflect.TypeOf(is[i]).Kind() == reflect.String {
+                                                                       enumVals = append(enumVals, is[i].(string))
+
+                                                               } else if reflect.TypeOf(is[1]).Kind() == reflect.Int {
+                                                                       enumVals = append(enumVals, strconv.Itoa(is[i].(int)))
+                                                               }
+                                                       }
+                                                       correctEnum.Enum = enumVals
+                                                       correctEnum.Type = "string"
+                                                       description := tDMap["description"]
+                                                       if description != nil {
+                                                               correctEnum.Description = description.(string)
+                                                       } else {
+                                                               if aOSlice[1] != nil {
+                                                                       mapInterface = aOSlice[1].(map[interface{}]interface{})
+                                                                       description := mapInterface["description"]
+                                                                       if description != nil {
+                                                                               correctEnum.Description = description.(string)
+                                                                       }
+                                                               }
+                                                       }
+                                                       schemas[typeName] = correctEnum
+                                               }
+                                       }
+                               }
+                               modM, err := yaml.Marshal(m)
+                               if err != nil {
+                                       log.Printf("yamlFile. Get err   #%v ", err)
+                               }
+                               err = ioutil.WriteFile(path, modM, 0644)
+                               if err != nil {
+                                       log.Printf("yamlFile. Get err   #%v ", err)
+                               }
+                       }
+               }
+       }
+       return nil
+}
diff --git a/invoker/internal/gentools/specificationfixer/specificationfixer.go b/invoker/internal/gentools/specificationfixer/specificationfixer.go
new file mode 100644 (file)
index 0000000..4257b65
--- /dev/null
@@ -0,0 +1,80 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2022: Nordix Foundation
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "flag"
+       "io/ioutil"
+       "log"
+
+       "gopkg.in/yaml.v2"
+)
+
+var apiDir *string
+
+func main() {
+       apiDir = flag.String("apidir", "", "Directory containing API definitions to fix")
+       flag.Parse()
+
+       m := getData("TS29571_CommonData.yaml")
+       components := m["components"]
+       cMap := components.(map[interface{}]interface{})
+       schemas := cMap["schemas"].(map[interface{}]interface{})
+       snssaiExtensionData := schemas["SnssaiExtension"].(map[interface{}]interface{})
+       props := snssaiExtensionData["properties"].(map[interface{}]interface{})
+       wildcardSdData := props["wildcardSd"].(map[interface{}]interface{})
+       delete(wildcardSdData, "enum")
+
+       writeFile("TS29571_CommonData.yaml", m)
+
+       m = getData("TS29222_CAPIF_Security_API.yaml")
+       components = m["components"]
+       cMap = components.(map[interface{}]interface{})
+       schemas = cMap["schemas"].(map[interface{}]interface{})
+       accessTokenReq := schemas["AccessTokenReq"].(map[interface{}]interface{})
+       accessTokenReq["type"] = "object"
+
+       writeFile("TS29222_CAPIF_Security_API.yaml", m)
+}
+
+func getData(filename string) map[string]interface{} {
+       yamlFile, err := ioutil.ReadFile(*apiDir + "/" + filename)
+       if err != nil {
+               log.Fatalf("Error reading yamlFile. #%v ", err)
+       }
+       m := make(map[string]interface{})
+       err = yaml.Unmarshal(yamlFile, m)
+       if err != nil {
+               log.Fatalf("Unmarshal: %v", err)
+       }
+       return m
+}
+
+func writeFile(filename string, data map[string]interface{}) {
+       modCommon, err := yaml.Marshal(data)
+       if err != nil {
+               log.Fatalf("Marshal: #%v ", err)
+       }
+       err = ioutil.WriteFile(*apiDir+"/"+filename, modCommon, 0644)
+       if err != nil {
+               log.Fatalf("Error writing yamlFile. #%v ", err)
+       }
+}
diff --git a/invoker/main.go b/invoker/main.go
new file mode 100644 (file)
index 0000000..e8dd6cf
--- /dev/null
@@ -0,0 +1,93 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023: Nordix Foundation
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "errors"
+       "flag"
+       "fmt"
+       "html/template"
+       "io"
+
+       log "github.com/sirupsen/logrus"
+
+       "github.com/labstack/echo/v4"
+       "oransc.org/nonrtric/capifinvoker/handler"
+)
+
+type TemplateRegistry struct {
+       templates map[string]*template.Template
+}
+
+func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
+       tmpl, ok := t.templates[name]
+       if !ok {
+               err := errors.New("Template not found -> " + name)
+               return err
+       }
+       return tmpl.ExecuteTemplate(w, "base", data)
+}
+
+func main() {
+
+       // Echo instance
+       e := echo.New()
+       e.Static("/", "view")
+       var capifCoreUrl string
+       flag.StringVar(&capifCoreUrl, "capifCoreUrl", "http://localhost:8090", "Url for CAPIF core")
+       var logLevelStr = flag.String("loglevel", "Info", "Log level")
+       var port = flag.Int("port", 9090, "Port for CAPIF Provider")
+
+       flag.Parse()
+
+       if loglevel, err := log.ParseLevel(*logLevelStr); err == nil {
+               log.SetLevel(loglevel)
+       }
+
+       templates := make(map[string]*template.Template)
+       templates["home.html"] = template.Must(template.ParseFiles("view/home.html", "view/base.html"))
+       templates["discovery.html"] = template.Must(template.ParseFiles("view/discovery.html", "view/base.html"))
+       templates["onboardinvoker.html"] = template.Must(template.ParseFiles("view/onboardinvoker.html", "view/base.html"))
+       templates["securitymethod.html"] = template.Must(template.ParseFiles("view/securitymethod.html", "view/base.html"))
+       templates["gettoken.html"] = template.Must(template.ParseFiles("view/gettoken.html", "view/base.html"))
+
+       e.Renderer = &TemplateRegistry{
+               templates: templates,
+       }
+
+       // Route => handler
+       e.GET("/", handler.HomeHandler)
+       e.POST("/", handler.HomeHandler)
+
+       e.GET("/discovery", handler.DiscoverAPIs(capifCoreUrl))
+
+       e.GET("/onboardinvoker", handler.OnboardingInvokerHandler)
+       e.POST("/onboardinvoker", handler.OnboardInvoker(capifCoreUrl))
+
+       e.GET("/securitymethod", handler.SecurityMethodHandler)
+       e.POST("/securitymethod", handler.ObtainSecurityMethod(capifCoreUrl))
+
+       e.GET("/gettoken", handler.GetTokenHandler)
+       e.POST("/gettoken", handler.ObtainToken(capifCoreUrl))
+
+       // Start the web server
+       e.Logger.Fatal(e.Start(fmt.Sprintf("0.0.0.0:%d", *port)))
+}
diff --git a/invoker/view/base.html b/invoker/view/base.html
new file mode 100644 (file)
index 0000000..da912e6
--- /dev/null
@@ -0,0 +1,53 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "base"}}
+  <!DOCTYPE html>
+  <html lang="en">
+    <head>
+        <!-- Required meta tags -->
+        <meta charset="utf-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        
+        <!-- CSS -->
+        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
+        <link rel="stylesheet"  type="text/css" href="./css/style.css">
+        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
+        <script language="JavaScript" type="text/javascript" src="./js/script.js"></script>
+        
+        <title>{{template "title" .}}</title>
+    </head>
+    <body>
+        <main>
+        <div class="container py-4">
+            <header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom text-dark">
+                <div class="col-4 text-center">
+                    <a class="text-body-emphasis mb-3 mb-md-0 me-md-auto link-body-emphasis text-decoration-none" href="/">
+                        <span class="fs-2">CAPIF Invoker</span>
+                    </a>
+                  </div>       
+            </header>
+            {{template "body" .}}
+        </div>
+        </main>
+        <!-- JS -->
+        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
+    </body>
+  </html>
+{{end}}
\ No newline at end of file
diff --git a/invoker/view/css/style.css b/invoker/view/css/style.css
new file mode 100644 (file)
index 0000000..1654f0c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+*/
+.callout {
+  padding: 20px;
+  margin: 20px 0;
+  border: 1px solid #eee;
+  border-left-width: 5px;
+  border-radius: 3px;
+}
+
+.bs-callout {
+  margin-top: -5px;
+}
+.callout-info {
+  border-left-color: #5bc0de;
+}
+
+.callout-info h4 {
+  color: #5bc0de;
+}
+
+.hiddenRow {
+  padding: 0 !important;
+}
\ No newline at end of file
diff --git a/invoker/view/discovery.html b/invoker/view/discovery.html
new file mode 100644 (file)
index 0000000..b582baa
--- /dev/null
@@ -0,0 +1,152 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "title"}}
+  CAPIF Invoker | {{index . "name"}}
+{{end}}
+
+{{define "body"}}
+
+{{if .isResponse}}
+<div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+      <h4 class="card-subtitle mb-3 text-body-secondary">Response from CAPIF core</h4>
+      <div class="callout callout-info"> 
+        <h5 class="card-subtitle mb-3 text-body-secondary">DiscoveredAPIs - ServiceAPIDescription</h5>
+        <div id="response"> 
+        </div>
+      </div>  
+
+      <div class="btns col-md-12 text-center">
+        <form action="/" method="GET">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Return to main page">
+          </form>
+      </div>
+    </div>
+  </div>
+  <script>
+    var htmlResponse = "{{.response}}"
+    const strData = JSON.parse(htmlResponse);
+    console.log(strData)
+    let index = 0
+    let out = "";
+    strData.serviceAPIDescriptions.forEach((api) => {
+        out += `
+          <h6>
+            ApiId:
+            <small id="ApiId" class="text-muted">${api.apiId}</small>
+          </h6>
+          <h6>
+            ApiName:
+            <small id="ApiName" class="text-muted">${api.apiName}</small>
+          </h6>
+          <h6>
+            Description:
+            <small id="Description" class="text-muted">${api.description}</small>
+          </h6>
+          
+          <h6>AefProfiles:</h6>
+          <div id="responseTable" class="table-responsive">
+            <table class="table accordion">
+              <thead>
+                 <tr>
+                    <th scope="col">AefId</th>
+                    <th scope="col">AefLocation</th>
+                    <th scope="col">DomainName</th>
+                    <th scope="col">Protocol</th>
+                    <th scope="col">SecurityMethods</th>
+                 </tr>
+              </thead>
+              <tbody id="data-output">
+                 <!-- Prodcuts from javascript file in here. -->
+                 ${printAefProfiles(api.aefProfiles, index)}
+              </tbody>
+           </table>
+          </div>
+        `;
+        index++;
+        document.querySelector("#response").innerHTML = out;
+    });
+  </script>
+{{- else}}
+    <div class="p-5 mb-4 bg-light rounded-3">
+        <div class="container-fluid py-5">
+            {{if .isError}}
+                <div class="alert alert-danger" role="alert">
+                    {{.response}}
+                </div>
+            {{end}}
+            {{if .isEmpty}}
+                <div class="alert alert-warning" role="alert">
+                    {{.response}}
+                </div>
+            {{end}}
+            <h5 class="card-subtitle mb-3 text-body-secondary">CAPIF_Discover_Service_API > Discover_Service_API</h5>
+            <form action="/discovery" method="GET">
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">API invoker identifier:</label>
+                    <input type="text" class="form-control" id="api-invoker-id" name="api-invoker-id" placeholder="invokerId" required>
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">API name:</label>
+                    <input type="text" class="form-control" id="api-name" name="api-name" placeholder="apiName it is set as {apiName} part of the URI " >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">API major version the URI:</label>
+                    <input type="text" class="form-control" id="api-version" name="api-version" placeholder="apiVersion" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Communication type used by the API:</label>
+                    <input type="text" class="form-control" id="comm-type" name="comm-type" placeholder="commType e.g. REQUEST_RESPONSE" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Protocol:</label>
+                    <input type="text" class="form-control" id="protocol" name="protocol" placeholder="protocol" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">AEF identifer:</label>
+                    <input type="text" class="form-control" id="aef-id" name="aef-id" placeholder="aefId" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Data formats used by the API:</label>
+                    <input type="text" class="form-control" id="data-format" name="data-format" placeholder="dataFormat e.g. serialization protocol JSON used" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Api category:</label>
+                    <input type="text" class="form-control" id="api-cat" name="api-cat" placeholder="apiCat" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Preferred Aef Location:</label>
+                    <input type="text" class="form-control" id="preferred-aef-loc" name="preferred-aef-loc" placeholder="preferredAefLoc" >
+                </div>
+                <div class="mb-3">
+                    <label for="apfId" class="form-label">Supported Features:</label>
+                    <input type="text" class="form-control" id="supported-features" name="supported-features" placeholder="suppFeat" >
+                </div>
+                <div class="btns col-md-12 text-center">
+                    <input class="btn btn-primary" type="submit" value="Submit">
+                    <input class="btn btn-secondary" formaction="/" type="submit" value="Cancel" formnovalidate>
+                </div>
+            </form>
+        </div>
+    </div>
+{{- end}}
+{{end}}
+
+
diff --git a/invoker/view/gettoken.html b/invoker/view/gettoken.html
new file mode 100644 (file)
index 0000000..fbe64ce
--- /dev/null
@@ -0,0 +1,102 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "title"}}
+  CAPIF Invoker
+{{end}}
+
+{{define "body"}}
+  {{if .isResponse}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+      <h4 class="card-subtitle mb-3 text-body-secondary">Response from CAPIF core</h4>
+      <div class="callout callout-info">
+        <h5 class="card-subtitle mb-3 text-body-secondary">Access Token Response</h5>
+        <div id="response" class="text-truncate">
+          <h6>
+            Access token:
+            <small id="accessToken" class="text-muted"></small>
+          </h6>
+          <h6>
+            Expires in:
+            <small id="expiresIn" class="text-muted"></small>
+          </h6>
+          <h6>
+            Scope:
+            <small id="scope" class="text-muted"></small>
+          </h6>
+          <h6>
+            Token type:
+            <small id="tokenType" class="text-muted"></small>
+          </h6>
+        </div>
+      </div>
+
+      <div class="btns col-md-12 text-center">
+        <form action="/" method="GET">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Return to main page">
+          </form>
+      </div>
+    </div>
+  </div>
+  <script>
+    var htmlResponse = "{{.response}}"
+    const strData = JSON.parse(htmlResponse);
+    document.getElementById("accessToken").innerHTML = strData.access_token;
+    document.getElementById("expiresIn").innerHTML = strData.expires_in;
+    document.getElementById("scope").innerHTML = strData.scope;
+    document.getElementById("tokenType").innerHTML = strData.token_type;
+  </script>
+  {{- else}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+        {{if .isError}}
+            <div class="alert alert-danger" role="alert">
+                {{.response}}
+            </div>
+        {{end}}
+      <h5 class="card-subtitle mb-3 text-body-secondary">CAPIF_Security_API > Obtain_Authorization</h5>
+      <form action="/gettoken" method="POST">
+        <div class="mb-3">
+          <label for="securityId" class="form-label">Security Id:</label>
+          <input type="text" class="form-control" id="securityId" name="securityId" placeholder="securityId" required>
+        </div>
+        <div class="mb-3">
+            <label for="clientId" class="form-label">Client Id:</label>
+            <input type="text" class="form-control" id="clientId" name="clientId" placeholder="clientId" required>
+        </div>
+        <div class="mb-3">
+            <label for="clientSecret" class="form-label">Client Secret:</label>
+            <input type="text" class="form-control" id="clientSecret" name="clientSecret" placeholder="clientSecret" >
+        </div>
+        <div class="mb-3">
+            <label for="scope" class="form-label">Scope:</label>
+            <input type="text" class="form-control" id="scope" name="scope" placeholder="scope" >
+        </div>
+        <div class="btns col-md-12 text-center">
+            <input class="btn btn-primary" type="submit" value="Submit">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Cancel" formnovalidate>
+        </div>
+      </form>
+    </div>
+  </div>
+  {{- end}}
+{{end}}
+
+
diff --git a/invoker/view/home.html b/invoker/view/home.html
new file mode 100644 (file)
index 0000000..59239d3
--- /dev/null
@@ -0,0 +1,73 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "title"}}
+  CAPIF Invoker
+{{end}}
+
+{{define "body"}}
+<div class="bd-example">
+<div class="accordion" id="accordionExample">
+    <div class="accordion-item">
+      <h2 class="accordion-header">
+        <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
+          CAPIF_API_Invoker_Management_API
+        </button>
+      </h2>
+      <div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionExample">
+        <div class="accordion-body">
+            <ul>
+              <li><a href="/onboardinvoker">Onboard_API_Invoker</a></li>
+              <li><a href="/offboardinvoker">Offboard_API_Invoker</a></li>
+            </ul>
+        </div>
+      </div>
+    </div>
+    <div class="accordion-item">
+      <h2 class="accordion-header">
+        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
+          CAPIF_Discover_Service_API
+        </button>
+      </h2>
+      <div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
+        <div class="accordion-body">
+            <ul>
+              <li><a href="/discovery">Discover published service APIs and retrieve a collection of APIs according to certain filter criteria.</a></li>
+            </ul>
+        </div>
+      </div>
+    </div>
+    <div class="accordion-item">
+      <h2 class="accordion-header">
+        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
+          CAPIF_Security_API
+        </button>
+      </h2>
+      <div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
+        <ul>
+          <li><a href="/securitymethod">Obtain_Security_Method</a></li>
+          <li><a href="/gettoken">Obtain_Authorization</a></li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</div>
+{{end}}
+
+
diff --git a/invoker/view/js/script.js b/invoker/view/js/script.js
new file mode 100644 (file)
index 0000000..e7ca85d
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+*/
+const isObject = (value) => typeof value === "object" && value !== null
+
+function checkValue(value){
+    return (isObject(value) ? value : "");
+}
+
+function printResources(resources) {
+    let res = Object.values(checkValue(resources));
+    let out = `<p class="lead">Resources:</p><ul>`;
+    res.forEach((r) => {
+        out += `<li>
+            <p>
+            <strong>CommType:</strong> ${r.commType}
+            <strong>CustOpName:</strong> ${r.custOpName} 
+            <strong>ResourceName:</strong> ${r.resourceName}
+            <strong>Uri:</strong> ${r.uri} 
+            <strong>Description:</strong> ${r.description}
+            <strong>Operations:</strong> ${Object.values(checkValue(r.operations))}
+            </p>
+            </li>`;
+    });
+    out += `</ul>`;
+    return out;
+}
+
+function printCustomOperations(custOperations) {
+    let operations = Object.values(checkValue(custOperations));
+    let out = `<p class="lead"> Custom Operations:</p><ul>`;
+    operations.forEach((o) => {
+        out += `<li>
+            <p>
+            <strong>CommType:</strong> ${o.commType}
+            <strong>CustOpName:</strong> ${o.custOpName} 
+            <strong>Description:</strong> ${o.description}
+            <strong>Operations:</strong> ${Object.values(checkValue(o.operations))}
+            </p>
+            </li>`;
+    });
+    out += `</ul>`;
+    return out;
+}
+
+function printVersions(versions) {
+    let vers = Object.values(checkValue(versions));
+    let out = `<p class="lead">Versions:</p><ul>`;
+    vers.forEach((v) => {
+        out += `<li>
+            <p>
+            <strong>ApiVersion:</strong> ${v.apiVersion} 
+            ${printCustomOperations(v.custOperations)}
+            ${printResources(v.resources)}
+            </p>
+            </li>`;
+    });
+    out += `</ul>`;
+    return out;
+}
+
+function printInterfaceDescription(description) {
+    let interfaceDescriptions = Object.values(checkValue(description));
+    let out = `<p class="lead">Interface Description:</p><ul>`;
+    interfaceDescriptions.forEach((d) => {
+        out += `<li>
+            <p>
+            <strong>Ipv4Addr:</strong> ${d.ipv4Addr} 
+            <strong>Ipv6Addr:</strong> ${d.ipv6Addr} 
+            <strong>Port:</strong> ${d.port} 
+            <strong>SecurityMethods:</strong> ${Object.values(checkValue(d.securityMethods))}
+            </p>
+            </li>`;
+    });
+    out += `</ul>`;
+    return out;
+}
+
+function printAefProfiles(aefProfiles, k){
+    let out = "";
+    let index = 0;
+    aefProfiles.forEach((aef) => {
+      out += `
+         <tr data-bs-toggle="collapse"  data-bs-target="#r${k}${index}">
+            <td>${aef.aefId}</td>
+            <td>${aef.aefLocation}</td>
+            <td>${aef.domainName}</td>
+            <td>${aef.protocol}</td>
+            <td>${Object.values(checkValue(aef.securityMethods))}</td>
+         </tr>
+         <tr class="collapse accordion-collapse" id="r${k}${index}" data-bs-parent=".table">
+            <td colspan="5"> 
+                <div id="demo1">
+                    ${printInterfaceDescription(aef.interfaceDescriptions)} 
+                    ${printVersions(aef.versions)}
+                </div> 
+            </td>
+        </tr>
+      `;
+      index++;
+    }); 
+    return out;
+}
+
+function printSecInfo(secInfo){
+    let out = "";
+    let index = 0;
+    secInfo.forEach((info) => {
+      out += `
+         <tr>
+            <td>${info.aefId}</td>
+            <td>${info.apiId}</td>
+            <td>${Object.values(checkValue(info.prefSecurityMethods))}</td>
+            <td>${info.selSecurityMethod}</td>
+         </tr>
+      `;
+      index++;
+    }); 
+    return out;
+}
diff --git a/invoker/view/onboardinvoker.html b/invoker/view/onboardinvoker.html
new file mode 100644 (file)
index 0000000..89179ef
--- /dev/null
@@ -0,0 +1,115 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "title"}}
+  CAPIF Invoker | {{index . "name"}}
+{{end}}
+
+{{define "body"}}
+{{if .isResponse}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+      <h4 class="card-subtitle mb-3 text-body-secondary">Response from CAPIF core</h4>
+      <div class="callout callout-info"> 
+        <h5 class="card-subtitle mb-3 text-body-secondary">APIInvokerEnrolmentDetails</h5>
+        <div id="response"> 
+          <h6>
+            Api InvokerId:
+            <small id="apiInvokerId" class="text-muted"></small>
+          </h6>
+          <h6>
+            Api Invoker Information:
+            <small id="apiInvokerInformation" class="text-muted"></small>
+          </h6>
+          <h6>
+            Notification Destination:
+            <small id="notificationDestination" class="text-muted"></small>
+          </h6>
+          <h6>Onboarding Information:</h6>
+          <ul>
+            <li><h6>
+                Api Invoker Certificate:
+                <small id="apiInvokerCertificate" class="text-muted"></small>
+              </h6></li>
+            <li><h6>
+                Api Invoker PublicKey:
+                <small id="apiInvokerPublicKey" class="text-muted"></small>
+              </h6></li>
+            <li><h6>
+                Onboarding Secret:
+                <small id="onboardingSecret" class="text-muted"></small>
+              </h6></li>
+        </ul>
+        <h6>API List:</h6>
+          <div id="responseTable">
+
+          </div>
+        </div>
+      </div>  
+
+      <div class="btns col-md-12 text-center">
+        <form action="/" method="GET">
+          <input class="btn btn-secondary" formaction="/" type="submit" value="Return to main page">
+        </form>
+      </div>
+    </div>
+  </div>
+  <script>
+
+    var htmlResponse = "{{.response}}"
+    const strData = JSON.parse(htmlResponse);
+
+    document.getElementById("apiInvokerId").innerHTML = strData.apiInvokerId;
+    document.getElementById("apiInvokerInformation").innerHTML = strData.apiInvokerInformation;
+    document.getElementById("notificationDestination").innerHTML = strData.notificationDestination;
+
+    document.getElementById("apiInvokerCertificate").innerHTML = strData.onboardingInformation['apiInvokerCertificate'];
+    document.getElementById("apiInvokerPublicKey").innerHTML = strData.onboardingInformation['apiInvokerPublicKey'];
+    document.getElementById("onboardingSecret").innerHTML = strData.onboardingInformation['onboardingSecret'];
+
+    var pretty = JSON.stringify(strData.apiList, undefined, 4);
+    document.getElementById("responseTable").innerHTML = pretty;
+
+  </script>
+{{- else}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+      {{if .isError}}
+        <div class="alert alert-danger" role="alert">
+          {{.response}}
+        </div>
+      {{end}}
+      <h5 class="card-subtitle mb-3 text-body-secondary">CAPIF_API_Invoker_Management_API > Onboard_API_Invoker</h5>
+      <form action="/onboardinvoker" method="POST">
+        <div class="mb-3">
+          <label for="enrolmentDetails" class="form-label">APIInvokerEnrolmentDetails:</label>
+          <textarea id="enrolmentDetails"  class="form-control" name="enrolmentDetails" rows="10" cols="60" required></textarea>
+        </div>
+        
+        <div class="btns col-md-12 text-center">
+            <input class="btn btn-primary" type="submit" value="Submit">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Cancel" formnovalidate>
+        </div>
+      </form>
+    </div>
+  </div>
+{{- end}}
+{{end}}
+
+
diff --git a/invoker/view/securitymethod.html b/invoker/view/securitymethod.html
new file mode 100644 (file)
index 0000000..3518488
--- /dev/null
@@ -0,0 +1,109 @@
+<!--
+   ========================LICENSE_START=================================
+   O-RAN-SC
+   %%
+   Copyright (C) 2023: Nordix Foundation
+   %%
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ========================LICENSE_END===================================
+-->
+{{define "title"}}
+  CAPIF Invoker
+{{end}}
+
+{{define "body"}}
+  {{if .isResponse}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+      <h4 class="card-subtitle mb-3 text-body-secondary">Response from CAPIF core</h4>
+      <div class="callout callout-info"> 
+        <h5 class="card-subtitle mb-3 text-body-secondary">ServiceAPIDescription</h5>
+        <div id="response"> 
+          <h6>
+            Description:
+            <small id="Description" class="text-muted"></small>
+          </h6>
+          <h6>
+            Notification Destination:
+            <small id="NotificationDestination" class="text-muted"></small>
+          </h6>
+          <h6>
+            Supported Features:
+            <small id="SupportedFeatures" class="text-muted"></small>
+          </h6>
+          
+          <h6>Security Information:</h6>
+          <div id="responseTable" class="table-responsive">
+            <table class="table table-striped">
+              <thead>
+                 <tr>
+                    <th scope="col">AefId</th>
+                    <th scope="col">ApiId</th>
+                    <th scope="col">PrefSecurityMethods</th>
+                    <th scope="col">SelSecurityMethod</th>
+                 </tr>
+              </thead>
+              <tbody id="data-output">
+                 <!-- Prodcuts from javascript file in here. -->
+              </tbody>
+           </table>
+          </div>
+        </div>
+      </div>  
+
+      <div class="btns col-md-12 text-center">
+        <form action="/" method="GET">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Return to main page">
+          </form>
+      </div>
+    </div>
+  </div>
+  <script>
+    var htmlResponse = "{{.response}}"
+    const strData = JSON.parse(htmlResponse);
+    document.getElementById("Description").innerHTML = strData.description;
+    document.getElementById("NotificationDestination").innerHTML = strData.notificationDestination;
+    document.getElementById("SupportedFeatures").innerHTML = strData.supportedFeatures;
+
+    let secInfo = Object.values(checkValue(strData.securityInfo));
+    document.querySelector("#data-output").innerHTML = printSecInfo(secInfo);
+  </script>
+  {{- else}}
+  <div class="p-5 mb-4 bg-light rounded-3">
+    <div class="container-fluid py-5">
+        {{if .isError}}
+            <div class="alert alert-danger" role="alert">
+                {{.response}}
+            </div>
+        {{end}}
+      <h5 class="card-subtitle mb-3 text-body-secondary">CAPIF_Security_API > Obtain_Security_Method</h5>
+      <form action="/securitymethod" method="POST">
+        <div class="mb-3">
+          <label for="apfId" class="form-label">Api invoker identifier:</label>
+          <input type="text" class="form-control" id="invokerId" name="invokerId" placeholder="invokerId" required>
+        </div>   
+        <div class="mb-3">
+            <label for="servSecurity" class="form-label">Service Security:</label>
+            <textarea id="servSecurity"  class="form-control" name="servSecurity" rows="10" cols="60"></textarea>
+          </div>     
+        <div class="btns col-md-12 text-center">
+            <input class="btn btn-primary" type="submit" value="Submit">
+            <input class="btn btn-secondary" formaction="/" type="submit" value="Cancel" formnovalidate>
+        </div>
+      </form>
+    </div>
+  </div>
+  {{- end}}
+{{end}}
+
+