github.com/cs3org/reva/v2@v2.27.7/pkg/publicshare/manager/json/json_test.go (about) 1 // Copyright 2018-2022 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 json_test 20 21 import ( 22 "context" 23 "os" 24 "path/filepath" 25 "sync" 26 "time" 27 28 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 29 link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" 30 providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 31 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 32 "github.com/cs3org/reva/v2/pkg/publicshare" 33 "github.com/cs3org/reva/v2/pkg/publicshare/manager/json" 34 "github.com/cs3org/reva/v2/pkg/publicshare/manager/json/persistence/cs3" 35 "github.com/cs3org/reva/v2/pkg/storage/utils/metadata" 36 "golang.org/x/crypto/bcrypt" 37 "google.golang.org/protobuf/proto" 38 "google.golang.org/protobuf/testing/protocmp" 39 40 . "github.com/onsi/ginkgo/v2" 41 . "github.com/onsi/gomega" 42 ) 43 44 var _ = Describe("Json", func() { 45 var ( 46 user1 = &userpb.User{ 47 Id: &userpb.UserId{ 48 Idp: "https://localhost:9200", 49 OpaqueId: "admin", 50 }, 51 } 52 53 sharedResource = &providerv1beta1.ResourceInfo{ 54 Id: &providerv1beta1.ResourceId{ 55 StorageId: "storageid", 56 OpaqueId: "opaqueid", 57 }, 58 ArbitraryMetadata: &providerv1beta1.ArbitraryMetadata{ 59 Metadata: map[string]string{ 60 "name": "publicshare", 61 }, 62 }, 63 } 64 grant = &link.Grant{ 65 Permissions: &link.PublicSharePermissions{ 66 Permissions: &providerv1beta1.ResourcePermissions{ 67 InitiateFileUpload: false, 68 }, 69 }, 70 } 71 72 m publicshare.Manager 73 tmpFile *os.File 74 ctx context.Context 75 ) 76 77 Context("with a file persistence layer", func() { 78 79 BeforeEach(func() { 80 var err error 81 tmpFile, err = os.CreateTemp("", "reva-unit-test-*.json") 82 Expect(err).ToNot(HaveOccurred()) 83 84 config := map[string]interface{}{ 85 "file": tmpFile.Name(), 86 "gateway_addr": "https://localhost:9200", 87 } 88 m, err = json.NewFile(config) 89 Expect(err).ToNot(HaveOccurred()) 90 91 ctx = ctxpkg.ContextSetUser(context.Background(), user1) 92 }) 93 94 AfterEach(func() { 95 os.Remove(tmpFile.Name()) 96 }) 97 98 Describe("Dump", func() { 99 JustBeforeEach(func() { 100 _, err := m.CreatePublicShare(ctx, user1, sharedResource, &link.Grant{ 101 Password: "foo", 102 }) 103 Expect(err).ToNot(HaveOccurred()) 104 }) 105 106 It("dumps all public shares", func() { 107 psharesChan := make(chan *publicshare.WithPassword) 108 pshares := []*publicshare.WithPassword{} 109 110 wg := sync.WaitGroup{} 111 wg.Add(1) 112 go func() { 113 for ps := range psharesChan { 114 if ps != nil { 115 pshares = append(pshares, ps) 116 } 117 } 118 wg.Done() 119 }() 120 err := m.(publicshare.DumpableManager).Dump(ctx, psharesChan) 121 Expect(err).ToNot(HaveOccurred()) 122 close(psharesChan) 123 wg.Wait() 124 Eventually(psharesChan).Should(BeClosed()) 125 126 Expect(len(pshares)).To(Equal(1)) 127 Expect(bcrypt.CompareHashAndPassword([]byte(pshares[0].Password), []byte("foo"))).To(Succeed()) 128 Expect(pshares[0].PublicShare.Creator).To(BeComparableTo(user1.Id, protocmp.Transform())) 129 Expect(pshares[0].PublicShare.ResourceId).To(BeComparableTo(sharedResource.Id, protocmp.Transform())) 130 }) 131 }) 132 133 Describe("Load", func() { 134 It("loads shares including state and mountpoint information", func() { 135 existingShare, err := m.CreatePublicShare(ctx, user1, sharedResource, &link.Grant{ 136 Password: "foo", 137 }) 138 Expect(err).ToNot(HaveOccurred()) 139 140 targetManager, err := json.NewMemory(map[string]interface{}{}) 141 Expect(err).ToNot(HaveOccurred()) 142 143 sharesChan := make(chan *publicshare.WithPassword) 144 145 wg := sync.WaitGroup{} 146 wg.Add(2) 147 go func() { 148 err := targetManager.(publicshare.LoadableManager).Load(ctx, sharesChan) 149 Expect(err).ToNot(HaveOccurred()) 150 wg.Done() 151 }() 152 go func() { 153 tmpShare := &publicshare.WithPassword{ 154 Password: "foo", 155 } 156 proto.Merge(&tmpShare.PublicShare, existingShare) 157 sharesChan <- tmpShare 158 close(sharesChan) 159 wg.Done() 160 }() 161 wg.Wait() 162 Eventually(sharesChan).Should(BeClosed()) 163 164 loadedPublicShare, err := targetManager.GetPublicShare(ctx, user1, &link.PublicShareReference{ 165 Spec: &link.PublicShareReference_Token{ 166 Token: existingShare.Token, 167 }, 168 }, false) 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(loadedPublicShare).ToNot(BeNil()) 171 }) 172 }) 173 }) 174 175 Context("with a cs3 persistence layer", func() { 176 var ( 177 tmpdir string 178 179 storage metadata.Storage 180 ) 181 182 BeforeEach(func() { 183 var err error 184 tmpdir, err = os.MkdirTemp("", "json-publicshare-manager-test") 185 Expect(err).ToNot(HaveOccurred()) 186 187 err = os.MkdirAll(tmpdir, 0755) 188 Expect(err).ToNot(HaveOccurred()) 189 190 storage, err = metadata.NewDiskStorage(tmpdir) 191 Expect(err).ToNot(HaveOccurred()) 192 193 persistence := cs3.New(storage) 194 Expect(persistence.Init(context.Background())).To(Succeed()) 195 196 m, err = json.New("https://localhost:9200", 11, 60, false, persistence) 197 Expect(err).ToNot(HaveOccurred()) 198 199 ctx = ctxpkg.ContextSetUser(context.Background(), user1) 200 }) 201 202 AfterEach(func() { 203 if tmpdir != "" { 204 os.RemoveAll(tmpdir) 205 } 206 }) 207 Describe("CreatePublicShare", func() { 208 It("creates public shares", func() { 209 ps, err := m.CreatePublicShare(ctx, user1, sharedResource, grant) 210 Expect(err).ToNot(HaveOccurred()) 211 Expect(ps).ToNot(BeNil()) 212 }) 213 }) 214 215 Describe("PublicShares", func() { 216 It("lists public shares", func() { 217 _, err := m.CreatePublicShare(ctx, user1, sharedResource, grant) 218 Expect(err).ToNot(HaveOccurred()) 219 220 ps, err := m.ListPublicShares(ctx, user1, []*link.ListPublicSharesRequest_Filter{}, false) 221 Expect(err).ToNot(HaveOccurred()) 222 Expect(len(ps)).To(Equal(1)) 223 Expect(ps[0].ResourceId).To(Equal(sharedResource.Id)) 224 }) 225 226 It("picks up shares from the storage", func() { 227 _, err := m.CreatePublicShare(ctx, user1, sharedResource, grant) 228 Expect(err).ToNot(HaveOccurred()) 229 230 // Reset manager 231 p := cs3.New(storage) 232 Expect(p.Init(context.Background())).To(Succeed()) 233 234 m, err = json.New("https://localhost:9200", 11, 60, false, p) 235 Expect(err).ToNot(HaveOccurred()) 236 237 ps, err := m.ListPublicShares(ctx, user1, []*link.ListPublicSharesRequest_Filter{}, false) 238 Expect(err).ToNot(HaveOccurred()) 239 Expect(len(ps)).To(Equal(1)) 240 Expect(ps[0].ResourceId).To(Equal(sharedResource.Id)) 241 }) 242 243 It("refreshes its cache before writing new data", func() { 244 _, err := m.CreatePublicShare(ctx, user1, sharedResource, grant) 245 Expect(err).ToNot(HaveOccurred()) 246 247 ps, err := m.ListPublicShares(ctx, user1, []*link.ListPublicSharesRequest_Filter{}, false) 248 Expect(err).ToNot(HaveOccurred()) 249 Expect(len(ps)).To(Equal(1)) 250 251 // Purge file on storage and make sure its mtime is newer than the cache 252 path := filepath.Join(tmpdir, "publicshares.json") 253 Expect(os.WriteFile(path, []byte("{}"), 0x644)).To(Succeed()) 254 t := time.Now().Add(5 * time.Minute) 255 Expect(os.Chtimes(path, t, t)).To(Succeed()) 256 257 _, err = m.CreatePublicShare(ctx, user1, sharedResource, grant) 258 Expect(err).ToNot(HaveOccurred()) 259 260 ps, err = m.ListPublicShares(ctx, user1, []*link.ListPublicSharesRequest_Filter{}, false) 261 Expect(err).ToNot(HaveOccurred()) 262 Expect(len(ps)).To(Equal(1)) // Make sure the first created public share is gone 263 }) 264 }) 265 }) 266 })