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 }