1
0
mirror of https://github.com/rancher/norman.git synced 2025-08-16 22:37:07 +00:00
norman/store/schema/schema_store.go
rmweir 2da1bd2ffc Add enable function and addFeature functions
Added enable function to schemas. This allows filtering of schemas
which is a required part of feature flagging in rancher. Added
addFeature functions to controller template for adding handlers that
can be disabled if their associated feature is disabled.
2019-07-02 12:18:40 -07:00

153 lines
4.5 KiB
Go

package schema
import (
"encoding/json"
"net/http"
"strings"
"github.com/rancher/norman/httperror"
"github.com/rancher/norman/store/empty"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/definition"
"github.com/rancher/norman/types/slice"
)
type Store struct {
empty.Store
}
func NewSchemaStore() types.Store {
return &Store{}
}
func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
for _, schema := range apiContext.Schemas.SchemasForVersion(*apiContext.Version) {
if strings.EqualFold(schema.ID, id) {
if schema.Enabled != nil {
if !schema.Enabled() {
return nil, httperror.NewAPIError(httperror.NotFound, "schema disabled")
}
}
schemaData := map[string]interface{}{}
data, err := json.Marshal(s.modifyForAccessControl(apiContext, *schema))
if err != nil {
return nil, err
}
return schemaData, json.Unmarshal(data, &schemaData)
}
}
return nil, httperror.NewAPIError(httperror.NotFound, "no such schema")
}
func (s *Store) modifyForAccessControl(context *types.APIContext, schema types.Schema) *types.Schema {
var resourceMethods []string
if slice.ContainsString(schema.ResourceMethods, http.MethodPut) && schema.CanUpdate(context) == nil {
resourceMethods = append(resourceMethods, http.MethodPut)
}
if slice.ContainsString(schema.ResourceMethods, http.MethodDelete) && schema.CanDelete(context) == nil {
resourceMethods = append(resourceMethods, http.MethodDelete)
}
if slice.ContainsString(schema.ResourceMethods, http.MethodGet) && schema.CanGet(context) == nil {
resourceMethods = append(resourceMethods, http.MethodGet)
}
var collectionMethods []string
if slice.ContainsString(schema.CollectionMethods, http.MethodPost) && schema.CanCreate(context) == nil {
collectionMethods = append(collectionMethods, http.MethodPost)
}
if slice.ContainsString(schema.CollectionMethods, http.MethodGet) && schema.CanList(context) == nil {
collectionMethods = append(collectionMethods, http.MethodGet)
}
schema.ResourceMethods = resourceMethods
schema.CollectionMethods = collectionMethods
return &schema
}
func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) {
return nil, nil
}
func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {
schemaMap := apiContext.Schemas.SchemasForVersion(*apiContext.Version)
schemas := make([]*types.Schema, 0, len(schemaMap))
schemaData := make([]map[string]interface{}, 0, len(schemaMap))
included := map[string]bool{}
for _, schema := range schemaMap {
if included[schema.ID] {
continue
}
if schema.Enabled != nil {
if !schema.Enabled() {
continue
}
}
if schema.CanList(apiContext) == nil || schema.CanGet(apiContext) == nil {
schemas = s.addSchema(apiContext, schema, schemaMap, schemas, included)
}
}
data, err := json.Marshal(schemas)
if err != nil {
return nil, err
}
return schemaData, json.Unmarshal(data, &schemaData)
}
func (s *Store) addSchema(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema {
included[schema.ID] = true
schemas = s.traverseAndAdd(apiContext, schema, schemaMap, schemas, included)
schemas = append(schemas, s.modifyForAccessControl(apiContext, *schema))
return schemas
}
func (s *Store) traverseAndAdd(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema {
for _, field := range schema.ResourceFields {
t := ""
subType := field.Type
for subType != t {
t = subType
subType = definition.SubType(t)
}
if refSchema, ok := schemaMap[t]; ok && !included[t] {
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
}
}
for _, action := range schema.ResourceActions {
for _, t := range []string{action.Output, action.Input} {
if t == "" {
continue
}
if refSchema, ok := schemaMap[t]; ok && !included[t] {
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
}
}
}
for _, action := range schema.CollectionActions {
for _, t := range []string{action.Output, action.Input} {
if t == "" {
continue
}
if refSchema, ok := schemaMap[t]; ok && !included[t] {
schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included)
}
}
}
return schemas
}