github.com/cs3org/reva/v2@v2.27.7/internal/http/services/preferences/preferences.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package preferences
    20  
    21  import (
    22  	"encoding/json"
    23  	"net/http"
    24  
    25  	preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1"
    26  	rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
    27  	"github.com/cs3org/reva/v2/pkg/appctx"
    28  	"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
    29  	"github.com/cs3org/reva/v2/pkg/rhttp/global"
    30  	"github.com/cs3org/reva/v2/pkg/sharedconf"
    31  	"github.com/go-chi/chi/v5"
    32  	"github.com/mitchellh/mapstructure"
    33  	"github.com/rs/zerolog"
    34  )
    35  
    36  func init() {
    37  	global.Register("preferences", New)
    38  }
    39  
    40  // Config holds the config options that for the preferences HTTP service
    41  type Config struct {
    42  	Prefix     string `mapstructure:"prefix"`
    43  	GatewaySvc string `mapstructure:"gatewaysvc"`
    44  }
    45  
    46  func (c *Config) init() {
    47  	if c.Prefix == "" {
    48  		c.Prefix = "preferences"
    49  	}
    50  	c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc)
    51  }
    52  
    53  type svc struct {
    54  	conf   *Config
    55  	router *chi.Mux
    56  }
    57  
    58  // New returns a new ocmd object
    59  func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) {
    60  
    61  	conf := &Config{}
    62  	if err := mapstructure.Decode(m, conf); err != nil {
    63  		return nil, err
    64  	}
    65  	conf.init()
    66  
    67  	r := chi.NewRouter()
    68  	s := &svc{
    69  		conf:   conf,
    70  		router: r,
    71  	}
    72  
    73  	if err := s.routerInit(log); err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	return s, nil
    78  }
    79  
    80  func (s *svc) routerInit(log *zerolog.Logger) error {
    81  	s.router.Get("/", s.handleGet)
    82  	s.router.Post("/", s.handlePost)
    83  
    84  	_ = chi.Walk(s.router, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
    85  		log.Debug().Str("service", "preferences").Str("method", method).Str("route", route).Int("middlewares", len(middlewares)).Msg("serving endpoint")
    86  		return nil
    87  	})
    88  
    89  	return nil
    90  }
    91  
    92  // Close performs cleanup.
    93  func (s *svc) Close() error {
    94  	return nil
    95  }
    96  
    97  func (s *svc) Prefix() string {
    98  	return s.conf.Prefix
    99  }
   100  
   101  func (s *svc) Unprotected() []string {
   102  	return []string{}
   103  }
   104  
   105  func (s *svc) Handler() http.Handler {
   106  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   107  		s.router.ServeHTTP(w, r)
   108  	})
   109  }
   110  
   111  func (s *svc) handleGet(w http.ResponseWriter, r *http.Request) {
   112  	ctx := r.Context()
   113  	log := appctx.GetLogger(ctx)
   114  
   115  	key := r.URL.Query().Get("key")
   116  	ns := r.URL.Query().Get("ns")
   117  
   118  	if key == "" || ns == "" {
   119  		w.WriteHeader(http.StatusBadRequest)
   120  		if _, err := w.Write([]byte("key or namespace query missing")); err != nil {
   121  			log.Error().Err(err).Msg("error writing to response")
   122  			w.WriteHeader(http.StatusInternalServerError)
   123  		}
   124  		return
   125  
   126  	}
   127  
   128  	client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc)
   129  	if err != nil {
   130  		log.Error().Err(err).Msg("error getting grpc gateway client")
   131  		w.WriteHeader(http.StatusInternalServerError)
   132  		return
   133  	}
   134  
   135  	res, err := client.GetKey(ctx, &preferences.GetKeyRequest{
   136  		Key: &preferences.PreferenceKey{
   137  			Namespace: ns,
   138  			Key:       key,
   139  		},
   140  	})
   141  	if err != nil {
   142  		log.Error().Err(err).Msg("error retrieving key")
   143  		w.WriteHeader(http.StatusInternalServerError)
   144  		return
   145  	}
   146  	if res.Status.Code != rpc.Code_CODE_OK {
   147  		if res.Status.Code == rpc.Code_CODE_NOT_FOUND {
   148  			w.WriteHeader(http.StatusNotFound)
   149  		} else {
   150  			w.WriteHeader(http.StatusInternalServerError)
   151  		}
   152  		log.Error().Interface("status", res.Status).Msg("error retrieving key")
   153  		return
   154  	}
   155  
   156  	js, err := json.Marshal(map[string]interface{}{
   157  		"namespace": ns,
   158  		"key":       key,
   159  		"value":     res.Val,
   160  	})
   161  	if err != nil {
   162  		log.Error().Err(err).Msg("error marshalling response")
   163  		w.WriteHeader(http.StatusInternalServerError)
   164  		return
   165  	}
   166  
   167  	w.Header().Set("Content-Type", "application/json")
   168  	if _, err = w.Write(js); err != nil {
   169  		log.Error().Err(err).Msg("error writing JSON response")
   170  		w.WriteHeader(http.StatusInternalServerError)
   171  		return
   172  	}
   173  
   174  }
   175  
   176  func (s *svc) handlePost(w http.ResponseWriter, r *http.Request) {
   177  	ctx := r.Context()
   178  	log := appctx.GetLogger(ctx)
   179  
   180  	key := r.FormValue("key")
   181  	ns := r.FormValue("ns")
   182  	val := r.FormValue("value")
   183  
   184  	if key == "" || ns == "" || val == "" {
   185  		w.WriteHeader(http.StatusBadRequest)
   186  		if _, err := w.Write([]byte("key, namespace or value parameter missing")); err != nil {
   187  			log.Error().Err(err).Msg("error writing to response")
   188  			w.WriteHeader(http.StatusInternalServerError)
   189  		}
   190  		return
   191  
   192  	}
   193  
   194  	client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc)
   195  	if err != nil {
   196  		log.Error().Err(err).Msg("error getting grpc gateway client")
   197  		w.WriteHeader(http.StatusInternalServerError)
   198  		return
   199  	}
   200  
   201  	res, err := client.SetKey(ctx, &preferences.SetKeyRequest{
   202  		Key: &preferences.PreferenceKey{
   203  			Namespace: ns,
   204  			Key:       key,
   205  		},
   206  		Val: val,
   207  	})
   208  	if err != nil {
   209  		log.Error().Err(err).Msg("error setting key")
   210  		w.WriteHeader(http.StatusInternalServerError)
   211  		return
   212  	}
   213  	if res.Status.Code != rpc.Code_CODE_OK {
   214  		w.WriteHeader(http.StatusInternalServerError)
   215  		log.Error().Interface("status", res.Status).Msg("error setting key")
   216  		return
   217  	}
   218  }