Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,51 @@
"_collection_link": "https://restless-escape-842597.postman.co/workspace/Open-AMT-Cloud-Toolkit~0d3a781d-7dbd-469f-b6ee-a5b75bda71ca/collection/4929283-eab0c07a-2ab9-4e7a-a631-f96e710199dd?action=share&source=collection_link&creator=4929283"
},
"item": [
{
"name": "Server",
"item": [
{
"name": "Get Server Features",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"Status code is 200\", function () {\r",
" pm.response.to.have.status(200);\r",
"});\r",
"\r",
"pm.test(\"Response contains ciraEnabled boolean\", function () {\r",
" var jsonData = pm.response.json();\r",
" pm.expect(jsonData).to.have.property(\"ciraEnabled\");\r",
" pm.expect(jsonData.ciraEnabled).to.be.a(\"boolean\");\r",
"});"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{protocol}}://{{host}}/api/v1/server/features",
"protocol": "{{protocol}}",
"host": [
"{{host}}"
],
"path": [
"api",
"v1",
"server",
"features"
]
}
},
"response": []
}
]
},
{
"name": "AMT",
"item": [
Expand Down
1 change: 1 addition & 0 deletions internal/controller/httpapi/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func NewRouter(handler *gin.Engine, l logger.Interface, t usecase.Usecases, cfg
v1.NewDeviceRoutes(h2, t.Devices, l)
v1.NewAmtRoutes(h2, t.Devices, t.AMTExplorer, t.Exporter, l)
v1.NewCIRACertRoutes(h2, l)
v1.NewServerRoutes(h2, cfg)
}

h := protected.Group("/v1/admin")
Expand Down
32 changes: 32 additions & 0 deletions internal/controller/httpapi/v1/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package v1

import (
"net/http"

"github.com/gin-gonic/gin"

"github.com/device-management-toolkit/console/config"
dto "github.com/device-management-toolkit/console/internal/entity/dto/v1"
)

type serverRoutes struct {
config *config.Config
}

// NewServerRoutes registers server-level capability endpoints. These expose how
// Console was started so clients can adapt their UI (e.g. show/hide the CIRA tab).
func NewServerRoutes(handler *gin.RouterGroup, cfg *config.Config) {
r := &serverRoutes{config: cfg}

h := handler.Group("/server")
{
h.GET("/features", r.getFeatures)
}
}

// getFeatures returns the server-level feature flags.
func (r *serverRoutes) getFeatures(c *gin.Context) {
c.JSON(http.StatusOK, dto.ServerFeatures{
CIRAEnabled: !r.config.DisableCIRA,
})
}
71 changes: 71 additions & 0 deletions internal/controller/httpapi/v1/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package v1

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"

"github.com/device-management-toolkit/console/config"
dto "github.com/device-management-toolkit/console/internal/entity/dto/v1"
)

func serverTestEngine(t *testing.T, disableCIRA bool) *gin.Engine {
t.Helper()

cfg := &config.Config{App: config.App{DisableCIRA: disableCIRA}}

engine := gin.New()
group := engine.Group("/api/v1")

NewServerRoutes(group, cfg)

return engine
}

func TestServerFeatures(t *testing.T) {
t.Parallel()

tests := []struct {
name string
disableCIRA bool
wantCIRAEnabled bool
}{
{
name: "CIRA enabled when not disabled",
disableCIRA: false,
wantCIRAEnabled: true,
},
{
name: "CIRA disabled",
disableCIRA: true,
wantCIRAEnabled: false,
},
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

engine := serverTestEngine(t, tt.disableCIRA)

req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "/api/v1/server/features", http.NoBody)
require.NoError(t, err)

w := httptest.NewRecorder()
engine.ServeHTTP(w, req)

require.Equal(t, http.StatusOK, w.Code)

var features dto.ServerFeatures
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &features))
require.Equal(t, tt.wantCIRAEnabled, features.CIRAEnabled)
})
}
}
3 changes: 3 additions & 0 deletions internal/controller/openapi/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ func (f *FuegoAdapter) RegisterRoutes() {

// Device Management
f.RegisterDeviceManagementRoutes()

// Server features
f.RegisterServerRoutes()
}

// Generates OpenAPI specification as JSON.
Expand Down
20 changes: 20 additions & 0 deletions internal/controller/openapi/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package openapi

import (
"github.com/go-fuego/fuego"

dto "github.com/device-management-toolkit/console/internal/entity/dto/v1"
)

func (f *FuegoAdapter) RegisterServerRoutes() {
fuego.Get(f.server, "/api/v1/server/features", f.getServerFeatures,
fuego.OptionTags("Server"),
fuego.OptionSummary("Get Server Features"),
fuego.OptionDescription("Retrieve server-level capability flags so clients can adapt their UI (e.g. show or hide the CIRA tab)"),
protectedRouteOptions(),
)
}

func (f *FuegoAdapter) getServerFeatures(_ fuego.ContextNoBody) (dto.ServerFeatures, error) {
return dto.ServerFeatures{}, nil
}
11 changes: 11 additions & 0 deletions internal/entity/dto/v1/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dto

type (
// ServerFeatures reports server-level capability flags so clients (e.g. the
// Sample Web UI) can toggle features that depend on how Console was started.
// New flags should be added here as additional fields rather than via a new
// endpoint.
ServerFeatures struct {
CIRAEnabled bool `json:"ciraEnabled" example:"true"`
}
)
Loading