-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathfeatures.go
98 lines (89 loc) · 3.37 KB
/
features.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package handler
import (
"context"
"net/http"
"reflect"
"strings"
"github.com/content-services/content-sources-backend/pkg/api"
"github.com/content-services/content-sources-backend/pkg/config"
ce "github.com/content-services/content-sources-backend/pkg/errors"
"github.com/content-services/content-sources-backend/pkg/rbac"
"github.com/labstack/echo/v4"
"github.com/redhatinsights/platform-go-middlewares/v2/identity"
"github.com/rs/zerolog/log"
"golang.org/x/exp/slices"
)
type FeaturesHandler struct {
}
func RegisterFeaturesRoutes(engine *echo.Group) {
fh := FeaturesHandler{}
addRepoRoute(engine, http.MethodGet, "/features/", fh.listFeatures, rbac.RbacVerbRead)
}
// ListFeatures godoc
// @Summary List Features within the application, whether they are enabled, and whether the requesting user can use them
// @ID listFeatures
// @Description Get features enables retrieving information about the features within an application, regardless of their current status (enabled or disabled) and the user's access to them.
// @Tags features
// @Accept json
// @Produce json
// @Success 200 {object} api.FeatureSet
// @Router /features/ [get]
func (fh *FeaturesHandler) listFeatures(c echo.Context) error {
set := make(api.FeatureSet)
elem := reflect.ValueOf(config.Get().Features)
for i := 0; i < elem.NumField(); i++ {
name := strings.ToLower(elem.Type().Field(i).Name)
value := elem.Field(i).Interface()
feature, valid := value.(config.Feature)
if !valid {
log.Logger.Error().Msgf("Could not load feature %v", feature)
continue
}
set[name] = api.Feature{
Enabled: feature.Enabled,
Accessible: accessible(c.Request().Context(), feature),
}
}
return c.JSON(http.StatusOK, set)
}
func accessible(ctx context.Context, feature config.Feature) bool {
if !feature.Enabled {
return false
}
if feature.Accounts == nil && feature.Users == nil && feature.Organizations == nil {
return true
}
identity := identity.GetIdentity(ctx)
if feature.Accounts != nil && slices.Contains(*feature.Accounts, identity.Identity.AccountNumber) {
return true
}
if feature.Organizations != nil && slices.Contains(*feature.Organizations, identity.Identity.OrgID) {
return true
}
if feature.Users != nil && ((identity.Identity.User != nil && slices.Contains(*feature.Users, identity.Identity.User.Username)) ||
(identity.Identity.ServiceAccount != nil && slices.Contains(*feature.Users, identity.Identity.ServiceAccount.Username))) {
return true
}
return false
}
func CheckSnapshotAccessible(ctx context.Context) (err error) {
if !config.Get().Features.Snapshots.Enabled {
return ce.NewErrorResponse(http.StatusBadRequest, "Snapshotting Feature is disabled.", "")
} else if accessible(ctx, config.Get().Features.Snapshots) {
return nil
} else {
return ce.NewErrorResponse(http.StatusBadRequest, "Cannot manage repository snapshots",
"Neither the user nor the account is allowed.")
}
}
func CheckAdminTaskAccessible(ctx context.Context) (err error) {
if !config.Get().Features.AdminTasks.Enabled {
return ce.NewErrorResponse(http.StatusBadRequest, "Cannot manage admin tasks",
"Admin tasks feature is disabled.")
} else if accessible(ctx, config.Get().Features.AdminTasks) {
return nil
} else {
return ce.NewErrorResponse(http.StatusBadRequest, "Cannot manage admin tasks",
"Neither the user nor account is allowed.")
}
}