From 5dda2b6cb02510b83f9573f2188a05359195b166 Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Fri, 18 Mar 2022 16:12:18 +0100 Subject: [PATCH] Preferences driver refactor and cbox sql implementation --- changelog/unreleased/preferences-refactor.md | 5 + cmd/reva/preferences.go | 15 +- cmd/revad/runtime/loader.go | 1 + go.mod | 3 +- go.sum | 67 +++++- .../services/authregistry/authregistry.go | 10 +- .../grpc/services/gateway/authprovider.go | 6 +- .../grpc/services/preferences/preferences.go | 137 ++++++----- .../http/services/appprovider/appprovider.go | 2 +- internal/http/services/loader/loader.go | 1 + .../http/services/preferences/preferences.go | 216 ++++++++++++++++++ pkg/cbox/loader/loader.go | 1 + pkg/cbox/preferences/sql/sql.go | 100 ++++++++ pkg/preferences/loader/loader.go | 25 ++ pkg/preferences/memory/memory.go | 79 +++++++ pkg/preferences/preferences.go | 31 +++ pkg/preferences/registry/registry.go | 34 +++ pkg/storage/favorite/loader/loader.go | 2 +- 18 files changed, 643 insertions(+), 92 deletions(-) create mode 100644 changelog/unreleased/preferences-refactor.md create mode 100644 internal/http/services/preferences/preferences.go create mode 100644 pkg/cbox/preferences/sql/sql.go create mode 100644 pkg/preferences/loader/loader.go create mode 100644 pkg/preferences/memory/memory.go create mode 100644 pkg/preferences/preferences.go create mode 100644 pkg/preferences/registry/registry.go diff --git a/changelog/unreleased/preferences-refactor.md b/changelog/unreleased/preferences-refactor.md new file mode 100644 index 00000000000..39f0ae04718 --- /dev/null +++ b/changelog/unreleased/preferences-refactor.md @@ -0,0 +1,5 @@ +Enhancement: Preferences driver refactor and cbox sql implementation + +This PR uses the updated CS3APIs which accepts a namespace in addition to a +single string key to recognize a user preference. It also refactors the GRPC +service to support multiple drivers and adds the cbox SQL implementation. \ No newline at end of file diff --git a/cmd/reva/preferences.go b/cmd/reva/preferences.go index 8a5f86e0a76..51471950bda 100644 --- a/cmd/reva/preferences.go +++ b/cmd/reva/preferences.go @@ -40,6 +40,7 @@ var preferencesCommand = func() *command { subcommand := cmd.Args()[0] key := cmd.Args()[1] + ns := cmd.Args()[2] client, err := getClient() if err != nil { @@ -50,12 +51,15 @@ var preferencesCommand = func() *command { switch subcommand { case "set": - if cmd.NArg() < 3 { + if cmd.NArg() < 4 { return errors.New("Invalid arguments: " + cmd.Usage()) } - value := cmd.Args()[2] + value := cmd.Args()[3] req := &preferences.SetKeyRequest{ - Key: key, + Key: &preferences.PreferenceKey{ + Namespace: ns, + Key: key, + }, Val: value, } @@ -70,7 +74,10 @@ var preferencesCommand = func() *command { case "get": req := &preferences.GetKeyRequest{ - Key: key, + Key: &preferences.PreferenceKey{ + Namespace: ns, + Key: key, + }, } res, err := client.GetKey(ctx, req) diff --git a/cmd/revad/runtime/loader.go b/cmd/revad/runtime/loader.go index 2dabdd5029c..fc917052a9f 100644 --- a/cmd/revad/runtime/loader.go +++ b/cmd/revad/runtime/loader.go @@ -40,6 +40,7 @@ import ( _ "github.com/cs3org/reva/pkg/ocm/provider/authorizer/loader" _ "github.com/cs3org/reva/pkg/ocm/share/manager/loader" _ "github.com/cs3org/reva/pkg/permission/manager/loader" + _ "github.com/cs3org/reva/pkg/preferences/loader" _ "github.com/cs3org/reva/pkg/publicshare/manager/loader" _ "github.com/cs3org/reva/pkg/rhttp/datatx/manager/loader" _ "github.com/cs3org/reva/pkg/share/cache/loader" diff --git a/go.mod b/go.mod index 7ab3d4f2a8c..2f515e1627f 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/cheggaaa/pb v1.0.29 github.com/coreos/go-oidc v2.2.1+incompatible github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e - github.com/cs3org/go-cs3apis v0.0.0-20220214084335-d975ab5d6e65 + github.com/cs3org/go-cs3apis v0.0.0-20220330081745-2ad58f5932b9 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 github.com/dgraph-io/ristretto v0.1.0 github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 @@ -92,5 +92,4 @@ go 1.16 replace ( github.com/eventials/go-tus => github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1 - google.golang.org/grpc => google.golang.org/grpc v1.26.0 // temporary downgrade ) diff --git a/go.sum b/go.sum index 74c94fc60be..d61bcc4336d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro= @@ -120,6 +121,7 @@ github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a h1:6tD4saJb8 github.com/andrewmostello/go-tus v0.0.0-20200314041820-904a9904af9a/go.mod h1:XYuK1S5+kS6FGhlIUFuZFPvWiSrOIoLk6+ro33Xce3Y= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -183,7 +185,16 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -210,10 +221,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJffz4pz0o1WuQxJ28+5x5JgaHD8= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= -github.com/cs3org/go-cs3apis v0.0.0-20211214102128-4e8745ab1654 h1:ha5tiuuFyDrwKUrVEc3TrRDFgTKVQ9NGDRmEP0PRPno= -github.com/cs3org/go-cs3apis v0.0.0-20211214102128-4e8745ab1654/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/go-cs3apis v0.0.0-20220214084335-d975ab5d6e65 h1:cee0dhBsF8KofV2TM52T41eOo1QLSgtgEZsjYmC5dhU= -github.com/cs3org/go-cs3apis v0.0.0-20220214084335-d975ab5d6e65/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20220330081745-2ad58f5932b9 h1:SuPu5Mc2mpz+J059XML+cMd0i5FZR4t/kROS3SaIsnU= +github.com/cs3org/go-cs3apis v0.0.0-20220330081745-2ad58f5932b9/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -241,7 +250,14 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exoscale/egoscale v0.46.0/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc= @@ -523,6 +539,7 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -548,6 +565,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -917,6 +935,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1080,6 +1099,7 @@ go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnv go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE= go.opentelemetry.io/otel/trace v1.4.1 h1:O+16qcdTrT7zxv2J6GejTPFinSwA++cYerC5iSiF8EQ= go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -1139,6 +1159,7 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1164,6 +1185,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1257,6 +1279,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1385,8 +1408,10 @@ golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13W golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1534,6 +1559,7 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -1570,8 +1596,38 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c h1:FqrtZMB5Wr+/RecOM3uPJNPfWR8Upb5hAPnt7PU6i4k= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1635,6 +1691,7 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/grpc/services/authregistry/authregistry.go b/internal/grpc/services/authregistry/authregistry.go index f3b3ab22620..a449a28be9e 100644 --- a/internal/grpc/services/authregistry/authregistry.go +++ b/internal/grpc/services/authregistry/authregistry.go @@ -116,17 +116,17 @@ func (s *service) ListAuthProviders(ctx context.Context, req *registrypb.ListAut return res, nil } -func (s *service) GetAuthProvider(ctx context.Context, req *registrypb.GetAuthProviderRequest) (*registrypb.GetAuthProviderResponse, error) { +func (s *service) GetAuthProviders(ctx context.Context, req *registrypb.GetAuthProvidersRequest) (*registrypb.GetAuthProvidersResponse, error) { pinfo, err := s.reg.GetProvider(ctx, req.Type) if err != nil { - return ®istrypb.GetAuthProviderResponse{ + return ®istrypb.GetAuthProvidersResponse{ Status: status.NewInternal(ctx, err, "error getting auth provider for type: "+req.Type), }, nil } - res := ®istrypb.GetAuthProviderResponse{ - Status: status.NewOK(ctx), - Provider: pinfo, + res := ®istrypb.GetAuthProvidersResponse{ + Status: status.NewOK(ctx), + Providers: []*registrypb.ProviderInfo{pinfo}, } return res, nil } diff --git a/internal/grpc/services/gateway/authprovider.go b/internal/grpc/services/gateway/authprovider.go index b526188b13a..fb2e5224578 100644 --- a/internal/grpc/services/gateway/authprovider.go +++ b/internal/grpc/services/gateway/authprovider.go @@ -213,7 +213,7 @@ func (s *svc) findAuthProvider(ctx context.Context, authType string) (authpb.Pro return nil, err } - res, err := c.GetAuthProvider(ctx, ®istry.GetAuthProviderRequest{ + res, err := c.GetAuthProviders(ctx, ®istry.GetAuthProvidersRequest{ Type: authType, }) @@ -222,9 +222,9 @@ func (s *svc) findAuthProvider(ctx context.Context, authType string) (authpb.Pro return nil, err } - if res.Status.Code == rpc.Code_CODE_OK && res.Provider != nil { + if res.Status.Code == rpc.Code_CODE_OK && res.Providers != nil && len(res.Providers) > 0 { // TODO(labkode): check for capabilities here - c, err := pool.GetAuthProviderServiceClient(res.Provider.Address) + c, err := pool.GetAuthProviderServiceClient(res.Providers[0].Address) if err != nil { err = errors.Wrap(err, "gateway: error getting an auth provider client") return nil, err diff --git a/internal/grpc/services/preferences/preferences.go b/internal/grpc/services/preferences/preferences.go index c51e874cdbc..32191e6ac67 100644 --- a/internal/grpc/services/preferences/preferences.go +++ b/internal/grpc/services/preferences/preferences.go @@ -20,38 +20,73 @@ package preferences import ( "context" - "sync" "google.golang.org/grpc" - userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" - preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1" - ctxpkg "github.com/cs3org/reva/pkg/ctx" + preferencespb "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1" + "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/preferences" + "github.com/cs3org/reva/pkg/preferences/registry" "github.com/cs3org/reva/pkg/rgrpc" "github.com/cs3org/reva/pkg/rgrpc/status" + "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) -type contextUserRequiredErr string - -func (err contextUserRequiredErr) Error() string { return string(err) } - func init() { rgrpc.Register("preferences", New) } -// m maps user to map of user preferences. -// m = map[userToken]map[key]value -var m = make(map[string]map[string]string) +type config struct { + Driver string `mapstructure:"driver"` + Drivers map[string]map[string]interface{} `mapstructure:"drivers"` +} -var mutex = &sync.Mutex{} +func (c *config) init() { + if c.Driver == "" { + c.Driver = "memory" + } +} + +type service struct { + conf *config + pm preferences.Manager +} + +func getPreferencesManager(c *config) (preferences.Manager, error) { + if f, ok := registry.NewFuncs[c.Driver]; ok { + return f(c.Drivers[c.Driver]) + } + return nil, errtypes.NotFound("driver not found: " + c.Driver) +} -type service struct{} +func parseConfig(m map[string]interface{}) (*config, error) { + c := &config{} + if err := mapstructure.Decode(m, c); err != nil { + err = errors.Wrap(err, "error decoding conf") + return nil, err + } + return c, nil +} // New returns a new PreferencesServiceServer func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - service := &service{} - return service, nil + c, err := parseConfig(m) + if err != nil { + return nil, err + } + + c.init() + + pm, err := getPreferencesManager(c) + if err != nil { + return nil, err + } + + return &service{ + conf: c, + pm: pm, + }, nil } func (s *service) Close() error { @@ -63,72 +98,32 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) Register(ss *grpc.Server) { - preferences.RegisterPreferencesAPIServer(ss, s) -} - -func getUser(ctx context.Context) (*userpb.User, error) { - u, ok := ctxpkg.ContextGetUser(ctx) - if !ok { - err := errors.Wrap(contextUserRequiredErr("userrequired"), "preferences: error getting user from ctx") - return nil, err - } - return u, nil + preferencespb.RegisterPreferencesAPIServer(ss, s) } -func (s *service) SetKey(ctx context.Context, req *preferences.SetKeyRequest) (*preferences.SetKeyResponse, error) { - key := req.Key - value := req.Val - - u, err := getUser(ctx) +func (s *service) SetKey(ctx context.Context, req *preferencespb.SetKeyRequest) (*preferencespb.SetKeyResponse, error) { + err := s.pm.SetKey(ctx, req.Key.Key, req.Key.Namespace, req.Val) if err != nil { - err = errors.Wrap(err, "preferences: failed to call getUser") - return &preferences.SetKeyResponse{ - Status: status.NewUnauthenticated(ctx, err, "user not found or invalid"), - }, err + return &preferencespb.SetKeyResponse{ + Status: status.NewInternal(ctx, err, "error setting key"), + }, nil } - name := u.Username - - mutex.Lock() - defer mutex.Unlock() - if len(m[name]) == 0 { - m[name] = map[string]string{key: value} - } else { - usersettings := m[name] - usersettings[key] = value - } - - return &preferences.SetKeyResponse{ + return &preferencespb.SetKeyResponse{ Status: status.NewOK(ctx), }, nil } -func (s *service) GetKey(ctx context.Context, req *preferences.GetKeyRequest) (*preferences.GetKeyResponse, error) { - key := req.Key - u, err := getUser(ctx) +func (s *service) GetKey(ctx context.Context, req *preferencespb.GetKeyRequest) (*preferencespb.GetKeyResponse, error) { + val, err := s.pm.GetKey(ctx, req.Key.Key, req.Key.Namespace) if err != nil { - err = errors.Wrap(err, "preferences: failed to call getUser") - return &preferences.GetKeyResponse{ - Status: status.NewUnauthenticated(ctx, err, "user not found or invalid"), - }, err + return &preferencespb.GetKeyResponse{ + Status: status.NewInternal(ctx, err, "error retrieving key"), + }, nil } - name := u.Username - - mutex.Lock() - defer mutex.Unlock() - if len(m[name]) != 0 { - if value, ok := m[name][key]; ok { - return &preferences.GetKeyResponse{ - Status: status.NewOK(ctx), - Val: value, - }, nil - } - } - - res := &preferences.GetKeyResponse{ - Status: status.NewNotFound(ctx, "key not found"), - Val: "", - } - return res, nil + return &preferencespb.GetKeyResponse{ + Status: status.NewOK(ctx), + Val: val, + }, nil } diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index ed101a0f3c0..b39d7ac0db2 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -47,7 +47,7 @@ func init() { global.Register("appprovider", New) } -// Config holds the config options that need to be passed down to all ocdav handlers +// Config holds the config options for the HTTP appprovider service type Config struct { Prefix string `mapstructure:"prefix"` GatewaySvc string `mapstructure:"gatewaysvc"` diff --git a/internal/http/services/loader/loader.go b/internal/http/services/loader/loader.go index 7548a93f323..6de231b478d 100644 --- a/internal/http/services/loader/loader.go +++ b/internal/http/services/loader/loader.go @@ -31,6 +31,7 @@ import ( _ "github.com/cs3org/reva/internal/http/services/ocmd" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocdav" _ "github.com/cs3org/reva/internal/http/services/owncloud/ocs" + _ "github.com/cs3org/reva/internal/http/services/preferences" _ "github.com/cs3org/reva/internal/http/services/prometheus" _ "github.com/cs3org/reva/internal/http/services/reverseproxy" _ "github.com/cs3org/reva/internal/http/services/siteacc" diff --git a/internal/http/services/preferences/preferences.go b/internal/http/services/preferences/preferences.go new file mode 100644 index 00000000000..cd544d98e43 --- /dev/null +++ b/internal/http/services/preferences/preferences.go @@ -0,0 +1,216 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package preferences + +import ( + "encoding/json" + "net/http" + + preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1" + rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/pkg/rhttp/global" + "github.com/cs3org/reva/pkg/sharedconf" + "github.com/go-chi/chi/v5" + "github.com/mitchellh/mapstructure" + "github.com/rs/zerolog" +) + +func init() { + global.Register("preferences", New) +} + +// Config holds the config options that for the preferences HTTP service +type Config struct { + Prefix string `mapstructure:"prefix"` + GatewaySvc string `mapstructure:"gatewaysvc"` +} + +func (c *Config) init() { + if c.Prefix == "" { + c.Prefix = "preferences" + } + c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc) +} + +type svc struct { + conf *Config + router *chi.Mux +} + +// New returns a new ocmd object +func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) { + + conf := &Config{} + if err := mapstructure.Decode(m, conf); err != nil { + return nil, err + } + conf.init() + + r := chi.NewRouter() + s := &svc{ + conf: conf, + router: r, + } + + if err := s.routerInit(); err != nil { + return nil, err + } + + return s, nil +} + +func (s *svc) routerInit() error { + s.router.Get("/", s.handleGet) + s.router.Post("/", s.handlePost) + return nil +} + +// Close performs cleanup. +func (s *svc) Close() error { + return nil +} + +func (s *svc) Prefix() string { + return s.conf.Prefix +} + +func (s *svc) Unprotected() []string { + return []string{} +} + +func (s *svc) Handler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.router.ServeHTTP(w, r) + }) +} + +func (s *svc) handleGet(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + log := appctx.GetLogger(ctx) + + key := r.URL.Query().Get("key") + ns := r.URL.Query().Get("ns") + + if key == "" || ns == "" { + w.WriteHeader(http.StatusBadRequest) + if _, err := w.Write([]byte("key or namespace query missing")); err != nil { + log.Error().Err(err).Msg("error writing to response") + w.WriteHeader(http.StatusInternalServerError) + } + return + + } + + client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) + if err != nil { + log.Error().Err(err).Msg("error getting grpc gateway client") + w.WriteHeader(http.StatusInternalServerError) + return + } + + res, err := client.GetKey(ctx, &preferences.GetKeyRequest{ + Key: &preferences.PreferenceKey{ + Namespace: ns, + Key: key, + }, + }) + if err != nil { + log.Error().Err(err).Msg("error retrieving key") + w.WriteHeader(http.StatusInternalServerError) + return + } + if res.Status.Code != rpc.Code_CODE_OK { + if res.Status.Code == rpc.Code_CODE_NOT_FOUND { + w.WriteHeader(http.StatusNotFound) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + log.Error().Interface("status", res.Status).Msg("error retrieving key") + return + } + + js, err := json.Marshal(map[string]interface{}{ + "namespace": ns, + "key": key, + "value": res.Val, + }) + if err != nil { + log.Error().Err(err).Msg("error marshalling response") + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + if _, err = w.Write(js); err != nil { + log.Error().Err(err).Msg("error writing JSON response") + w.WriteHeader(http.StatusInternalServerError) + return + } + +} + +func (s *svc) handlePost(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + log := appctx.GetLogger(ctx) + + key := r.FormValue("key") + ns := r.FormValue("ns") + val := r.FormValue("value") + + if key == "" || ns == "" || val == "" { + w.WriteHeader(http.StatusBadRequest) + if _, err := w.Write([]byte("key, namespace or value parameter missing")); err != nil { + log.Error().Err(err).Msg("error writing to response") + w.WriteHeader(http.StatusInternalServerError) + } + return + + } + + client, err := pool.GetGatewayServiceClient(s.conf.GatewaySvc) + if err != nil { + log.Error().Err(err).Msg("error getting grpc gateway client") + w.WriteHeader(http.StatusInternalServerError) + return + } + + res, err := client.SetKey(ctx, &preferences.SetKeyRequest{ + Key: &preferences.PreferenceKey{ + Namespace: ns, + Key: key, + }, + Val: val, + }) + if err != nil { + log.Error().Err(err).Msg("error setting key") + w.WriteHeader(http.StatusInternalServerError) + return + } + if res.Status.Code != rpc.Code_CODE_OK { + if res.Status.Code == rpc.Code_CODE_NOT_FOUND { + w.WriteHeader(http.StatusNotFound) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + log.Error().Interface("status", res.Status).Msg("error setting key") + return + } +} diff --git a/pkg/cbox/loader/loader.go b/pkg/cbox/loader/loader.go index 0dd9d07c4b3..1e5baa9d0fa 100644 --- a/pkg/cbox/loader/loader.go +++ b/pkg/cbox/loader/loader.go @@ -22,6 +22,7 @@ import ( // Load cbox specific drivers. _ "github.com/cs3org/reva/pkg/cbox/favorite/sql" _ "github.com/cs3org/reva/pkg/cbox/group/rest" + _ "github.com/cs3org/reva/pkg/cbox/preferences/sql" _ "github.com/cs3org/reva/pkg/cbox/publicshare/sql" _ "github.com/cs3org/reva/pkg/cbox/share/sql" _ "github.com/cs3org/reva/pkg/cbox/storage/eoshomewrapper" diff --git a/pkg/cbox/preferences/sql/sql.go b/pkg/cbox/preferences/sql/sql.go new file mode 100644 index 00000000000..67ba2ad7319 --- /dev/null +++ b/pkg/cbox/preferences/sql/sql.go @@ -0,0 +1,100 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sql + +import ( + "context" + "database/sql" + "fmt" + + ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/preferences" + "github.com/cs3org/reva/pkg/preferences/registry" + "github.com/mitchellh/mapstructure" +) + +func init() { + registry.Register("sql", New) +} + +type config struct { + DbUsername string `mapstructure:"db_username"` + DbPassword string `mapstructure:"db_password"` + DbHost string `mapstructure:"db_host"` + DbPort int `mapstructure:"db_port"` + DbName string `mapstructure:"db_name"` +} + +type mgr struct { + c *config + db *sql.DB +} + +// New returns an instance of the cbox sql preferences manager. +func New(m map[string]interface{}) (preferences.Manager, error) { + c := &config{} + if err := mapstructure.Decode(m, c); err != nil { + return nil, err + } + + db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", c.DbUsername, c.DbPassword, c.DbHost, c.DbPort, c.DbName)) + if err != nil { + return nil, err + } + + return &mgr{ + c: c, + db: db, + }, nil +} + +func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { + user, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + return errtypes.UserRequired("preferences: error getting user from ctx") + } + query := `INSERT INTO oc_preferences(userid, appid, configkey, configvalue) values(?, ?, ?, ?) ON DUPLICATE KEY UPDATE configvalue = ?` + params := []interface{}{user.Id.OpaqueId, namespace, key, value, value} + stmt, err := m.db.Prepare(query) + if err != nil { + return err + } + + if _, err = stmt.Exec(params...); err != nil { + return err + } + return nil +} + +func (m *mgr) GetKey(ctx context.Context, key, namespace string) (string, error) { + user, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + return "", errtypes.UserRequired("preferences: error getting user from ctx") + } + query := `SELECT configvalue FROM oc_preferences WHERE userid=? AND appid=? AND configkey=?` + var val string + if err := m.db.QueryRow(query, user.Id.OpaqueId, namespace, key).Scan(&val); err != nil { + if err == sql.ErrNoRows { + return "", errtypes.NotFound(namespace + ":" + key) + } + return "", err + } + return val, nil +} diff --git a/pkg/preferences/loader/loader.go b/pkg/preferences/loader/loader.go new file mode 100644 index 00000000000..a7b4d2c46c2 --- /dev/null +++ b/pkg/preferences/loader/loader.go @@ -0,0 +1,25 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package loader + +import ( + // Load preferences drivers. + _ "github.com/cs3org/reva/pkg/preferences/memory" + // Add your own here +) diff --git a/pkg/preferences/memory/memory.go b/pkg/preferences/memory/memory.go new file mode 100644 index 00000000000..b2c285e79d9 --- /dev/null +++ b/pkg/preferences/memory/memory.go @@ -0,0 +1,79 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package memory + +import ( + "context" + "sync" + + ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/errtypes" + "github.com/cs3org/reva/pkg/preferences" + "github.com/cs3org/reva/pkg/preferences/registry" +) + +func init() { + registry.Register("memory", New) +} + +type mgr struct { + sync.RWMutex + keys map[string]map[string]string +} + +// New returns an instance of the in-memory preferences manager. +func New(m map[string]interface{}) (preferences.Manager, error) { + return &mgr{keys: make(map[string]map[string]string)}, nil +} + +func (m *mgr) SetKey(ctx context.Context, key, namespace, value string) error { + u, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + return errtypes.UserRequired("preferences: error getting user from ctx") + } + m.Lock() + defer m.Unlock() + + userKey := u.Id.OpaqueId + + if len(m.keys[userKey]) == 0 { + m.keys[userKey] = map[string]string{key: value} + } else { + m.keys[userKey][key] = value + } + return nil +} + +func (m *mgr) GetKey(ctx context.Context, key, namespace string) (string, error) { + u, ok := ctxpkg.ContextGetUser(ctx) + if !ok { + return "", errtypes.UserRequired("preferences: error getting user from ctx") + } + m.RLock() + defer m.RUnlock() + + userKey := u.Id.OpaqueId + + if len(m.keys[userKey]) != 0 { + if value, ok := m.keys[userKey][key]; ok { + return value, nil + } + } + return "", errtypes.NotFound("preferences: key not found") +} diff --git a/pkg/preferences/preferences.go b/pkg/preferences/preferences.go new file mode 100644 index 00000000000..4f417396cb2 --- /dev/null +++ b/pkg/preferences/preferences.go @@ -0,0 +1,31 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package preferences + +import ( + "context" +) + +// Manager defines an interface for a preferences manager. +type Manager interface { + // SetKey sets a key under a specified namespace. + SetKey(ctx context.Context, key, namespace, value string) error + // GetKey returns the value for a combination of key and namespace, if set. + GetKey(ctx context.Context, key, namespace string) (string, error) +} diff --git a/pkg/preferences/registry/registry.go b/pkg/preferences/registry/registry.go new file mode 100644 index 00000000000..a8ca108f2d4 --- /dev/null +++ b/pkg/preferences/registry/registry.go @@ -0,0 +1,34 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package registry + +import "github.com/cs3org/reva/pkg/preferences" + +// NewFunc is the function that preferences implementations +// should register at init time. +type NewFunc func(map[string]interface{}) (preferences.Manager, error) + +// NewFuncs is a map containing all the registered preferences implementations. +var NewFuncs = map[string]NewFunc{} + +// Register registers a new preferences function. +// Not safe for concurrent use. Safe for use from package init. +func Register(name string, f NewFunc) { + NewFuncs[name] = f +} diff --git a/pkg/storage/favorite/loader/loader.go b/pkg/storage/favorite/loader/loader.go index de90e7223c3..7ebcb6cbd26 100644 --- a/pkg/storage/favorite/loader/loader.go +++ b/pkg/storage/favorite/loader/loader.go @@ -19,7 +19,7 @@ package loader import ( - // Load share cache drivers. + // Load storage favorite drivers. _ "github.com/cs3org/reva/pkg/storage/favorite/memory" // Add your own here )