bump reva to feature/guest-links branch

This commit is contained in:
Ralf Haferkamp
2026-04-23 17:07:00 +02:00
committed by Ralf Haferkamp
parent 3be224127e
commit 066cef17c4
102 changed files with 1345 additions and 734 deletions
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+125 -48
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -116,6 +116,60 @@ func (UserType) EnumDescriptor() ([]byte, []int) {
return file_cs3_identity_user_v1beta1_resources_proto_rawDescGZIP(), []int{0}
}
// The status of a user.
type UserStatus int32
const (
// The user is active and allowed to log in.
UserStatus_USER_STATUS_ACTIVE UserStatus = 0
// The user can log in but its validity is about to expire.
// The actual grace period the user is granted depends on its tenant's policy.
UserStatus_USER_STATUS_EXPIRING UserStatus = 1
// The user is valid but it has been blocked from login in its tenant.
UserStatus_USER_STATUS_BLOCKED UserStatus = 2
)
// Enum value maps for UserStatus.
var (
UserStatus_name = map[int32]string{
0: "USER_STATUS_ACTIVE",
1: "USER_STATUS_EXPIRING",
2: "USER_STATUS_BLOCKED",
}
UserStatus_value = map[string]int32{
"USER_STATUS_ACTIVE": 0,
"USER_STATUS_EXPIRING": 1,
"USER_STATUS_BLOCKED": 2,
}
)
func (x UserStatus) Enum() *UserStatus {
p := new(UserStatus)
*p = x
return p
}
func (x UserStatus) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (UserStatus) Descriptor() protoreflect.EnumDescriptor {
return file_cs3_identity_user_v1beta1_resources_proto_enumTypes[1].Descriptor()
}
func (UserStatus) Type() protoreflect.EnumType {
return &file_cs3_identity_user_v1beta1_resources_proto_enumTypes[1]
}
func (x UserStatus) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use UserStatus.Descriptor instead.
func (UserStatus) EnumDescriptor() ([]byte, []int) {
return file_cs3_identity_user_v1beta1_resources_proto_rawDescGZIP(), []int{1}
}
// ExternalIdentity represents an external identifier of a user.
// This can be populated when multiple identities collapse onto
// the same user, for example when signing in with e-mail or with
@@ -306,6 +360,11 @@ type User struct {
// OPTIONAL.
// The group id of this user in the Unix world.
GidNumber int64 `protobuf:"varint,9,opt,name=gid_number,json=gidNumber,proto3" json:"gid_number,omitempty"`
// OPTIONAL.
// The status of this user in the tenant it belongs to.
// Useful for tenants implementing a users lifecycle,
// otherwise it defaults to ACTIVE.
Status UserStatus `protobuf:"varint,10,opt,name=status,proto3,enum=cs3.identity.user.v1beta1.UserStatus" json:"status,omitempty"`
}
func (x *User) Reset() {
@@ -403,6 +462,13 @@ func (x *User) GetGidNumber() int64 {
return 0
}
func (x *User) GetStatus() UserStatus {
if x != nil {
return x.Status
}
return UserStatus_USER_STATUS_ACTIVE
}
var File_cs3_identity_user_v1beta1_resources_proto protoreflect.FileDescriptor
var file_cs3_identity_user_v1beta1_resources_proto_rawDesc = []byte{
@@ -431,7 +497,7 @@ var file_cs3_identity_user_v1beta1_resources_proto_rawDesc = []byte{
0x74, 0x69, 0x74, 0x79, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x52, 0x12, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0xba, 0x02, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12,
0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0xf9, 0x02, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12,
0x31, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x73,
0x33, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x52, 0x02,
@@ -451,38 +517,47 @@ var file_cs3_identity_user_v1beta1_resources_proto_rawDesc = []byte{
0x62, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x69, 0x64, 0x4e, 0x75,
0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x64, 0x4e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x2a, 0xe7, 0x01, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65,
0x12, 0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e,
0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x01, 0x12, 0x17,
0x0a, 0x13, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x43, 0x4f,
0x4e, 0x44, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x03, 0x12, 0x19,
0x0a, 0x15, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x4c,
0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x53, 0x45,
0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x10, 0x05, 0x12, 0x17,
0x0a, 0x13, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x45, 0x44, 0x45,
0x52, 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x53, 0x45, 0x52, 0x5f,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x57, 0x45, 0x49, 0x47, 0x48, 0x54,
0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x08, 0x42, 0xfa, 0x01,
0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x73, 0x33, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42,
0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73,
0x33, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x73, 0x33, 0x61, 0x70, 0x69, 0x73, 0x2f,
0x63, 0x73, 0x33, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x75, 0x73, 0x65,
0x72, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31,
0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x49, 0x55, 0xaa, 0x02, 0x19, 0x43, 0x73,
0x33, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e,
0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x19, 0x43, 0x73, 0x33, 0x5c, 0x49, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x62, 0x65,
0x74, 0x61, 0x31, 0xe2, 0x02, 0x25, 0x43, 0x73, 0x33, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c,
0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x43, 0x73,
0x33, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x55, 0x73, 0x65,
0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x62, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x63, 0x73, 0x33, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e,
0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x2a, 0xe7, 0x01, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12,
0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56,
0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a,
0x13, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x43, 0x4f, 0x4e,
0x44, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x03, 0x12, 0x19, 0x0a,
0x15, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x4c, 0x49,
0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x53, 0x45, 0x52,
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x10, 0x05, 0x12, 0x17, 0x0a,
0x13, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x45, 0x44, 0x45, 0x52,
0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x57, 0x45, 0x49, 0x47, 0x48, 0x54, 0x10,
0x07, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
0x50, 0x41, 0x43, 0x45, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x08, 0x2a, 0x57, 0x0a, 0x0a,
0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x53,
0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
0x53, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13,
0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x42, 0x4c, 0x4f, 0x43,
0x4b, 0x45, 0x44, 0x10, 0x02, 0x42, 0xfa, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x73,
0x33, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73, 0x33, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x6f, 0x2d,
0x63, 0x73, 0x33, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x63, 0x73, 0x33, 0x2f, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03,
0x43, 0x49, 0x55, 0xaa, 0x02, 0x19, 0x43, 0x73, 0x33, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca,
0x02, 0x19, 0x43, 0x73, 0x33, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x55,
0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x25, 0x43, 0x73,
0x33, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x5c,
0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64,
0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x43, 0x73, 0x33, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x3a, 0x3a, 0x55, 0x73, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74,
0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -497,25 +572,27 @@ func file_cs3_identity_user_v1beta1_resources_proto_rawDescGZIP() []byte {
return file_cs3_identity_user_v1beta1_resources_proto_rawDescData
}
var file_cs3_identity_user_v1beta1_resources_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_cs3_identity_user_v1beta1_resources_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_cs3_identity_user_v1beta1_resources_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_cs3_identity_user_v1beta1_resources_proto_goTypes = []interface{}{
(UserType)(0), // 0: cs3.identity.user.v1beta1.UserType
(*ExternalIdentity)(nil), // 1: cs3.identity.user.v1beta1.ExternalIdentity
(*UserId)(nil), // 2: cs3.identity.user.v1beta1.UserId
(*User)(nil), // 3: cs3.identity.user.v1beta1.User
(*v1beta1.Opaque)(nil), // 4: cs3.types.v1beta1.Opaque
(UserStatus)(0), // 1: cs3.identity.user.v1beta1.UserStatus
(*ExternalIdentity)(nil), // 2: cs3.identity.user.v1beta1.ExternalIdentity
(*UserId)(nil), // 3: cs3.identity.user.v1beta1.UserId
(*User)(nil), // 4: cs3.identity.user.v1beta1.User
(*v1beta1.Opaque)(nil), // 5: cs3.types.v1beta1.Opaque
}
var file_cs3_identity_user_v1beta1_resources_proto_depIdxs = []int32{
0, // 0: cs3.identity.user.v1beta1.UserId.type:type_name -> cs3.identity.user.v1beta1.UserType
1, // 1: cs3.identity.user.v1beta1.UserId.external_identities:type_name -> cs3.identity.user.v1beta1.ExternalIdentity
2, // 2: cs3.identity.user.v1beta1.User.id:type_name -> cs3.identity.user.v1beta1.UserId
4, // 3: cs3.identity.user.v1beta1.User.opaque:type_name -> cs3.types.v1beta1.Opaque
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
2, // 1: cs3.identity.user.v1beta1.UserId.external_identities:type_name -> cs3.identity.user.v1beta1.ExternalIdentity
3, // 2: cs3.identity.user.v1beta1.User.id:type_name -> cs3.identity.user.v1beta1.UserId
5, // 3: cs3.identity.user.v1beta1.User.opaque:type_name -> cs3.types.v1beta1.Opaque
1, // 4: cs3.identity.user.v1beta1.User.status:type_name -> cs3.identity.user.v1beta1.UserStatus
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_cs3_identity_user_v1beta1_resources_proto_init() }
@@ -566,7 +643,7 @@ func file_cs3_identity_user_v1beta1_resources_proto_init() {
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_cs3_identity_user_v1beta1_resources_proto_rawDesc,
NumEnums: 1,
NumEnums: 2,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -116,21 +116,26 @@ const (
Filter_TYPE_SPACE_ID Filter_Type = 7
Filter_TYPE_STATE Filter_Type = 8
Filter_TYPE_GRANTEE Filter_Type = 9
// Filter shares by whether the shared resource is a space root.
// When the term `space_root` is true, only shares on space roots are returned.
// When false, shares on space roots are excluded.
Filter_TYPE_SPACE_ROOT Filter_Type = 10
)
// Enum value maps for Filter_Type.
var (
Filter_Type_name = map[int32]string{
0: "TYPE_INVALID",
1: "TYPE_NO",
2: "TYPE_RESOURCE_ID",
3: "TYPE_OWNER",
4: "TYPE_CREATOR",
5: "TYPE_GRANTEE_TYPE",
6: "TYPE_EXCLUDE_DENIALS",
7: "TYPE_SPACE_ID",
8: "TYPE_STATE",
9: "TYPE_GRANTEE",
0: "TYPE_INVALID",
1: "TYPE_NO",
2: "TYPE_RESOURCE_ID",
3: "TYPE_OWNER",
4: "TYPE_CREATOR",
5: "TYPE_GRANTEE_TYPE",
6: "TYPE_EXCLUDE_DENIALS",
7: "TYPE_SPACE_ID",
8: "TYPE_STATE",
9: "TYPE_GRANTEE",
10: "TYPE_SPACE_ROOT",
}
Filter_Type_value = map[string]int32{
"TYPE_INVALID": 0,
@@ -143,6 +148,7 @@ var (
"TYPE_SPACE_ID": 7,
"TYPE_STATE": 8,
"TYPE_GRANTEE": 9,
"TYPE_SPACE_ROOT": 10,
}
)
@@ -773,6 +779,7 @@ type Filter struct {
// *Filter_SpaceId
// *Filter_State
// *Filter_Grantee
// *Filter_SpaceRoot
Term isFilter_Term `protobuf_oneof:"term"`
}
@@ -871,6 +878,13 @@ func (x *Filter) GetGrantee() *v1beta1.Grantee {
return nil
}
func (x *Filter) GetSpaceRoot() bool {
if x, ok := x.GetTerm().(*Filter_SpaceRoot); ok {
return x.SpaceRoot
}
return false
}
type isFilter_Term interface {
isFilter_Term()
}
@@ -903,6 +917,11 @@ type Filter_Grantee struct {
Grantee *v1beta1.Grantee `protobuf:"bytes,9,opt,name=grantee,proto3,oneof"`
}
type Filter_SpaceRoot struct {
// Used with TYPE_SPACE_ROOT.
SpaceRoot bool `protobuf:"varint,10,opt,name=space_root,json=spaceRoot,proto3,oneof"`
}
func (*Filter_ResourceId) isFilter_Term() {}
func (*Filter_Owner) isFilter_Term() {}
@@ -917,6 +936,8 @@ func (*Filter_State) isFilter_Term() {}
func (*Filter_Grantee) isFilter_Term() {}
func (*Filter_SpaceRoot) isFilter_Term() {}
var File_cs3_sharing_collaboration_v1beta1_resources_proto protoreflect.FileDescriptor
var file_cs3_sharing_collaboration_v1beta1_resources_proto_rawDesc = []byte{
@@ -1034,7 +1055,7 @@ var file_cs3_sharing_collaboration_v1beta1_resources_proto_rawDesc = []byte{
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63,
0x73, 0x33, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd8, 0x05, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8e, 0x06, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65,
0x72, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x2e, 0x2e, 0x63, 0x73, 0x33, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f,
0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65,
@@ -1067,47 +1088,50 @@ var file_cs3_sharing_collaboration_v1beta1_resources_proto_rawDesc = []byte{
0x0b, 0x32, 0x25, 0x2e, 0x63, 0x73, 0x33, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x48, 0x00, 0x52, 0x07, 0x67, 0x72, 0x61, 0x6e,
0x74, 0x65, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0b,
0x0a, 0x07, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x44, 0x10,
0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10,
0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x4f,
0x52, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x41, 0x4e,
0x54, 0x45, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x4e, 0x49, 0x41,
0x4c, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50, 0x41,
0x43, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x07, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x47, 0x52, 0x41, 0x4e, 0x54, 0x45, 0x45, 0x10, 0x09, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x65, 0x72,
0x6d, 0x2a, 0x72, 0x0a, 0x0a, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x49,
0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x52,
0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10,
0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45,
0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x53,
0x48, 0x41, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43,
0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0xb3, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x73,
0x33, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62,
0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x42,
0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73,
0x33, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x73, 0x33, 0x61, 0x70, 0x69, 0x73, 0x2f,
0x63, 0x73, 0x33, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6c, 0x6c,
0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x3b, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76,
0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x53, 0x43, 0xaa, 0x02, 0x21, 0x43,
0x73, 0x33, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x61,
0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31,
0xca, 0x02, 0x21, 0x43, 0x73, 0x33, 0x5c, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x43,
0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x62,
0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2d, 0x43, 0x73, 0x33, 0x5c, 0x53, 0x68, 0x61, 0x72, 0x69,
0x6e, 0x67, 0x5c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x43, 0x73, 0x33, 0x3a, 0x3a, 0x53, 0x68, 0x61, 0x72,
0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x74, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x6f, 0x6f,
0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x73, 0x70, 0x61, 0x63, 0x65,
0x52, 0x6f, 0x6f, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a,
0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12,
0x0b, 0x0a, 0x07, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x44,
0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x57, 0x4e, 0x45, 0x52,
0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
0x4f, 0x52, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x41,
0x4e, 0x54, 0x45, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x4e, 0x49,
0x41, 0x4c, 0x53, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x50,
0x41, 0x43, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x07, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x08, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x47, 0x52, 0x41, 0x4e, 0x54, 0x45, 0x45, 0x10, 0x09, 0x12, 0x13, 0x0a, 0x0f, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x53, 0x50, 0x41, 0x43, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x0a, 0x42,
0x06, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x2a, 0x72, 0x0a, 0x0a, 0x53, 0x68, 0x61, 0x72, 0x65,
0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x48, 0x41, 0x52, 0x45, 0x5f, 0x53,
0x54, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x17,
0x0a, 0x13, 0x53, 0x48, 0x41, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45,
0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x45,
0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10,
0x02, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45,
0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0xb3, 0x02, 0x0a, 0x25,
0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x73, 0x33, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e,
0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31,
0x62, 0x65, 0x74, 0x61, 0x31, 0x42, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73, 0x33, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x73,
0x33, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x63, 0x73, 0x33, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x69, 0x6e,
0x67, 0x2f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f,
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x43,
0x53, 0x43, 0xaa, 0x02, 0x21, 0x43, 0x73, 0x33, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67,
0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56,
0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xca, 0x02, 0x21, 0x43, 0x73, 0x33, 0x5c, 0x53, 0x68, 0x61,
0x72, 0x69, 0x6e, 0x67, 0x5c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0xe2, 0x02, 0x2d, 0x43, 0x73, 0x33,
0x5c, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x5c, 0x47,
0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x43, 0x73, 0x33,
0x3a, 0x3a, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x3a, 0x43, 0x6f, 0x6c, 0x6c, 0x61,
0x62, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x65, 0x74, 0x61,
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -1294,6 +1318,7 @@ func file_cs3_sharing_collaboration_v1beta1_resources_proto_init() {
(*Filter_SpaceId)(nil),
(*Filter_State)(nil),
(*Filter_Grantee)(nil),
(*Filter_SpaceRoot)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2018-2025 CERN
// Copyright 2018-2026 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -414,38 +414,45 @@ func SpaceEnabled(r *provider.UpdateStorageSpaceResponse, req *provider.UpdateSt
}
// SpaceShared converts the response to an event
// func SpaceShared(req *provider.AddGrantRequest, executant, sharer *user.UserId, grantee *provider.Grantee) events.SpaceShared {
func SpaceShared(r *provider.AddGrantResponse, req *provider.AddGrantRequest, executant *user.User) events.SpaceShared {
id := storagespace.FormatStorageID(req.Ref.ResourceId.StorageId, req.Ref.ResourceId.SpaceId)
func SpaceShared(r *collaboration.CreateShareResponse, executant *user.User) events.SpaceShared {
id := storagespace.FormatStorageID(r.GetShare().GetResourceId().GetStorageId(), r.GetShare().GetResourceId().GetSpaceId())
return events.SpaceShared{
Executant: executant.GetId(),
Creator: req.Grant.Creator,
GranteeUserID: req.Grant.GetGrantee().GetUserId(),
GranteeGroupID: req.Grant.GetGrantee().GetGroupId(),
Creator: r.Share.GetCreator(),
GranteeUserID: r.Share.GetGrantee().GetUserId(),
GranteeGroupID: r.Share.GetGrantee().GetGroupId(),
ID: &provider.StorageSpaceId{OpaqueId: id},
Timestamp: time.Now(),
}
}
// SpaceShareUpdated converts the response to an events
func SpaceShareUpdated(r *provider.UpdateGrantResponse, req *provider.UpdateGrantRequest, executant *user.User) events.SpaceShareUpdated {
id := storagespace.FormatStorageID(req.Ref.ResourceId.StorageId, req.Ref.ResourceId.SpaceId)
func SpaceShareUpdated(r *collaboration.UpdateShareResponse, executant *user.User) events.SpaceShareUpdated {
id := storagespace.FormatStorageID(r.GetShare().GetResourceId().GetStorageId(), r.GetShare().GetResourceId().GetSpaceId())
return events.SpaceShareUpdated{
Executant: executant.GetId(),
GranteeUserID: req.Grant.GetGrantee().GetUserId(),
GranteeGroupID: req.Grant.GetGrantee().GetGroupId(),
GranteeUserID: r.GetShare().GetGrantee().GetUserId(),
GranteeGroupID: r.GetShare().GetGrantee().GetGroupId(),
ID: &provider.StorageSpaceId{OpaqueId: id},
Timestamp: time.Now(),
}
}
// SpaceUnshared converts the response to an event
func SpaceUnshared(r *provider.RemoveGrantResponse, req *provider.RemoveGrantRequest, executant *user.User) events.SpaceUnshared {
id := storagespace.FormatStorageID(req.Ref.ResourceId.StorageId, req.Ref.ResourceId.SpaceId)
func SpaceUnshared(r *collaboration.RemoveShareResponse, req *collaboration.RemoveShareRequest, executant *user.User) events.SpaceUnshared {
var (
userid *user.UserId
groupid *group.GroupId
rid *provider.ResourceId
)
_ = utils.ReadJSONFromOpaque(r.Opaque, "granteeuserid", &userid)
_ = utils.ReadJSONFromOpaque(r.Opaque, "granteegroupid", &groupid)
_ = utils.ReadJSONFromOpaque(r.Opaque, "resourceid", &rid)
id := storagespace.FormatStorageID(rid.StorageId, rid.SpaceId)
return events.SpaceUnshared{
Executant: executant.GetId(),
GranteeUserID: req.Grant.GetGrantee().GetUserId(),
GranteeGroupID: req.Grant.GetGrantee().GetGroupId(),
GranteeUserID: userid,
GranteeGroupID: groupid,
ID: &provider.StorageSpaceId{OpaqueId: id},
Timestamp: time.Now(),
}
@@ -81,15 +81,30 @@ func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error
switch v := res.(type) {
case *collaboration.CreateShareResponse:
if isSuccess(v) {
ev = ShareCreated(v, executant)
if utils.ExistsInOpaque(v.Opaque, "noevent") {
break
}
if utils.ExistsInOpaque(v.Opaque, "spacegrant") {
ev = SpaceShared(v, executant)
} else {
ev = ShareCreated(v, executant)
}
}
case *collaboration.RemoveShareResponse:
if isSuccess(v) {
ev = ShareRemoved(v, req.(*collaboration.RemoveShareRequest), executant)
if utils.ExistsInOpaque(v.Opaque, "spacegrant") {
ev = SpaceUnshared(v, req.(*collaboration.RemoveShareRequest), executant)
} else {
ev = ShareRemoved(v, req.(*collaboration.RemoveShareRequest), executant)
}
}
case *collaboration.UpdateShareResponse:
if isSuccess(v) {
ev = ShareUpdated(v, req.(*collaboration.UpdateShareRequest), executant)
if utils.ExistsInOpaque(v.Opaque, "spacegrant") {
ev = SpaceShareUpdated(v, executant)
} else {
ev = ShareUpdated(v, req.(*collaboration.UpdateShareRequest), executant)
}
}
case *collaboration.UpdateReceivedShareResponse:
if isSuccess(v) {
@@ -117,24 +132,6 @@ func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error
if isSuccess(v) {
ev = OCMCoreShareCreated(v, req.(*ocmcore.CreateOCMCoreShareRequest), executant)
}
case *provider.AddGrantResponse:
// TODO: update CS3 APIs
// FIXME these should be part of the RemoveGrantRequest object
// https://github.com/owncloud/ocis/issues/4312
r := req.(*provider.AddGrantRequest)
if isSuccess(v) && utils.ExistsInOpaque(r.Opaque, "spacegrant") {
ev = SpaceShared(v, r, executant)
}
case *provider.UpdateGrantResponse:
r := req.(*provider.UpdateGrantRequest)
if isSuccess(v) && utils.ExistsInOpaque(r.Opaque, "spacegrant") {
ev = SpaceShareUpdated(v, r, executant)
}
case *provider.RemoveGrantResponse:
r := req.(*provider.RemoveGrantRequest)
if isSuccess(v) && utils.ExistsInOpaque(r.Opaque, "spacegrant") {
ev = SpaceUnshared(v, req.(*provider.RemoveGrantRequest), executant)
}
case *provider.CreateContainerResponse:
if isSuccess(v) {
ev = ContainerCreated(v, req.(*provider.CreateContainerRequest), ownerID, executant)
@@ -36,6 +36,8 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/opencloud-eu/reva/v2/pkg/conversions"
"github.com/rs/zerolog/log"
"google.golang.org/grpc/codes"
"github.com/golang-jwt/jwt/v5"
@@ -226,6 +228,52 @@ func (s *svc) CreateStorageSpace(ctx context.Context, req *provider.CreateStorag
}, nil
}
// If the create space is not a "personal" space, we add a Share to the ShareProvider to give the creator
// of the space "manager" access to it.
// Note: the DecomposedFS storagadriver already adds a grant to the space root giving that access, the "CreateShare"
// here is happeing so that that grant is also visible when listing permission (shares) on the spaceroot.
if req.GetType() != "personal" && createRes.GetStatus().GetCode() == rpc.Code_CODE_OK {
rollbackFn := func() {
dsRes, dsErr := s.DeleteStorageSpace(ctx, &provider.DeleteStorageSpaceRequest{
Id: createRes.GetStorageSpace().GetId(),
})
if dsErr != nil || dsRes.GetStatus().GetCode() != rpc.Code_CODE_OK {
log.Error().Err(dsErr).Interface("status", dsRes.GetStatus()).Interface("space_id", createRes.GetStorageSpace().GetId()).Msg("failed to delete space during rollback")
}
}
u := ctxpkg.ContextMustGetUser(ctx)
shareReq := &collaborationv1beta1.CreateShareRequest{
ResourceInfo: &provider.ResourceInfo{
Id: createRes.GetStorageSpace().GetRoot(),
},
Grant: &collaborationv1beta1.ShareGrant{
Grantee: &provider.Grantee{
Type: provider.GranteeType_GRANTEE_TYPE_USER,
Id: &provider.Grantee_UserId{
UserId: u.GetId(),
},
},
Permissions: &collaborationv1beta1.SharePermissions{
Permissions: conversions.NewManagerRole().CS3ResourcePermissions(),
},
},
}
csResp, err := s.CreateShare(ctx, shareReq)
if err != nil || csResp.GetStatus().GetCode() != rpc.Code_CODE_OK {
log.Error().Err(err).Interface("status", csResp.GetStatus()).Interface("space_id", createRes.GetStorageSpace().GetId()).Msg("failed to create initial share for space creator, rolling back space creation")
rollbackFn()
shareErrMsg := "failed to create initial share for space creator"
if err == nil {
shareErrMsg = csResp.GetStatus().GetMessage()
}
return &provider.CreateStorageSpaceResponse{
Status: status.NewInternal(ctx, shareErrMsg),
}, nil
}
}
return createRes, nil
}
@@ -150,7 +150,12 @@ func (s *svc) updateShare(ctx context.Context, req *collaboration.UpdateShareReq
Expiration: res.GetShare().GetExpiration(),
Creator: creator.GetId(),
}
updateGrantStatus, err := s.updateGrant(ctx, res.GetShare().GetResourceId(), grant, nil)
var opaque *typesv1beta1.Opaque
if refIsSpaceRoot(res.GetShare().GetResourceId()) {
opaque = utils.SpaceGrantOpaque()
utils.AppendPlainToOpaque(opaque, "spacetype", utils.ReadPlainFromOpaque(req.GetOpaque(), "spacetype"))
}
updateGrantStatus, err := s.updateGrant(ctx, res.GetShare().GetResourceId(), grant, opaque)
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling updateGrant")
@@ -175,11 +180,7 @@ func (s *svc) updateSpaceShare(ctx context.Context, req *collaboration.UpdateSha
var st *rpc.Status
var err error
// TODO: change CS3 APIs
opaque := &typesv1beta1.Opaque{
Map: map[string]*typesv1beta1.OpaqueEntry{
"spacegrant": {},
},
}
opaque := utils.SpaceGrantOpaque()
utils.AppendPlainToOpaque(opaque, "spacetype", utils.ReadPlainFromOpaque(req.Opaque, "spacetype"))
if grants.PermissionsEqual(req.Share.GetPermissions().GetPermissions(), &provider.ResourcePermissions{}) {
@@ -613,13 +614,18 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques
if s.c.CommitShareToStorageGrant {
// If the share is a denial we call denyGrant instead.
var status *rpc.Status
var opaque *typesv1beta1.Opaque
if refIsSpaceRoot(req.ResourceInfo.Id) {
opaque = utils.SpaceGrantOpaque()
utils.AppendPlainToOpaque(opaque, "spacetype", req.ResourceInfo.GetSpace().GetSpaceType())
}
if grants.PermissionsEqual(req.Grant.Permissions.Permissions, &provider.ResourcePermissions{}) {
status, err = s.denyGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, nil)
status, err = s.denyGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, opaque)
if err != nil {
return nil, errors.Wrap(err, "gateway: error denying grant in storage")
}
} else {
status, err = s.addGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, req.Grant.Permissions.Permissions, req.Grant.Expiration, nil)
status, err = s.addGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, req.Grant.Permissions.Permissions, req.Grant.Expiration, opaque)
if err != nil {
appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg(err.Error())
rollBackFn(status)
@@ -628,7 +634,7 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques
}
switch status.Code {
case rpc.Code_CODE_OK:
case rpc.Code_CODE_OK, rpc.Code_CODE_ALREADY_EXISTS:
// ok
case rpc.Code_CODE_UNIMPLEMENTED:
appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring")
@@ -653,11 +659,7 @@ func (s *svc) addSpaceShare(ctx context.Context, req *collaboration.CreateShareR
var st *rpc.Status
var err error
// TODO: change CS3 APIs
opaque := &typesv1beta1.Opaque{
Map: map[string]*typesv1beta1.OpaqueEntry{
"spacegrant": {},
},
}
opaque := utils.SpaceGrantOpaque()
utils.AppendPlainToOpaque(
opaque,
"spacetype",
@@ -742,9 +744,16 @@ func (s *svc) removeShare(ctx context.Context, req *collaboration.RemoveShareReq
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling RemoveShare")
}
if res.Status.Code != rpc.Code_CODE_OK {
return res, nil
}
if s.c.CommitShareToStorageGrant {
removeGrantStatus, err := s.removeGrant(ctx, share.ResourceId, share.Grantee, share.Permissions.Permissions, nil)
var opaque *typesv1beta1.Opaque
if refIsSpaceRoot(share.ResourceId) {
opaque = utils.SpaceGrantOpaque()
}
removeGrantStatus, err := s.removeGrant(ctx, share.ResourceId, share.Grantee, share.Permissions.Permissions, opaque)
if err != nil {
return nil, errors.Wrap(err, "gateway: error removing grant from storage")
}
@@ -780,11 +789,7 @@ func (s *svc) removeSpaceShare(ctx context.Context, ref *provider.ResourceId, gr
}
// TODO: change CS3 APIs
opaque := &typesv1beta1.Opaque{
Map: map[string]*typesv1beta1.OpaqueEntry{
"spacegrant": {},
},
}
opaque := utils.SpaceGrantOpaque()
removeGrantStatus, err := s.removeGrant(ctx, ref, grantee, permissions, opaque)
if err != nil {
return nil, errors.Wrap(err, "gateway: error removing grant from storage")
@@ -46,6 +46,7 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/rgrpc"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/share"
"github.com/opencloud-eu/reva/v2/pkg/sharedconf"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/pkg/errors"
@@ -1093,12 +1094,8 @@ func (s *service) resolveAcceptedShare(ctx context.Context, ref *provider.Refere
if ref.ResourceId.OpaqueId == utils.ShareStorageProviderID && ref.Path != "." {
lsRes, err := sharingCollaborationClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{
Filters: []*collaboration.Filter{
{
Type: collaboration.Filter_TYPE_STATE,
Term: &collaboration.Filter_State{
State: collaboration.ShareState_SHARE_STATE_ACCEPTED,
},
},
share.StateFilter(collaboration.ShareState_SHARE_STATE_ACCEPTED),
share.SpaceRootFilter(false),
// TODO filter by mountpoint?
},
})
@@ -1179,12 +1176,8 @@ func (s *service) fetchAcceptedShares(ctx context.Context, opaque *typesv1beta1.
lsRes, err := sharingCollaborationClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{
Filters: []*collaboration.Filter{
{
Type: collaboration.Filter_TYPE_STATE,
Term: &collaboration.Filter_State{
State: collaboration.ShareState_SHARE_STATE_ACCEPTED,
},
},
share.StateFilter(collaboration.ShareState_SHARE_STATE_ACCEPTED),
share.SpaceRootFilter(false),
},
})
if err != nil {
@@ -27,10 +27,12 @@ import (
"strings"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/rs/zerolog"
@@ -54,6 +56,9 @@ const (
_fieldMaskPathMountPoint = "mount_point"
_fieldMaskPathPermissions = "permissions"
_fieldMaskPathState = "state"
_spaceTypePersonal = "personal"
_spaceTypeProject = "project"
_spaceTypeVirtual = "virtual"
)
func init() {
@@ -166,13 +171,6 @@ func (s *service) isPathAllowed(path string) bool {
func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShareRequest) (*collaboration.CreateShareResponse, error) {
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)
// Grants must not allow grant permissions
if HasGrantPermissions(req.GetGrant().GetPermissions().GetPermissions()) {
return &collaboration.CreateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}
// check if the grantee is a user or group
if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_USER {
// check if the tenantId of the user matches the tenantId of the target user
@@ -202,8 +200,8 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
}, nil
}
// use logged in user Idp as default, if the Grantee does not have an IDP set.
if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_USER && req.GetGrant().GetGrantee().GetUserId().GetIdp() == "" {
// use logged in user Idp as default.
req.GetGrant().GetGrantee().Id = &provider.Grantee_UserId{
UserId: &userpb.UserId{
OpaqueId: req.GetGrant().GetGrantee().GetUserId().GetOpaqueId(),
@@ -211,6 +209,16 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
Type: userpb.UserType_USER_TYPE_PRIMARY},
}
}
// some for group grantees
if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_GROUP && req.GetGrant().GetGrantee().GetGroupId().GetIdp() == "" {
// use logged in user Idp as default.
req.GetGrant().GetGrantee().Id = &provider.Grantee_GroupId{
GroupId: &grouppb.GroupId{
OpaqueId: req.GetGrant().GetGrantee().GetGroupId().GetOpaqueId(),
Idp: user.GetId().GetIdp(),
Type: grouppb.GroupType_GROUP_TYPE_REGULAR},
}
}
sRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: req.GetResourceInfo().GetId()}})
if err != nil {
@@ -225,6 +233,55 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
Status: status.NewPermissionDenied(ctx, nil, "no permission to add grants on shared resource"),
}, err
}
isSpaceRoot := utils.IsSpaceRoot(sRes.GetInfo())
var noEvent bool
if isSpaceRoot {
if sRes.GetInfo().GetSpace().GetSpaceType() == _spaceTypePersonal || sRes.GetInfo().GetSpace().GetSpaceType() == _spaceTypeVirtual {
return &collaboration.CreateShareResponse{Status: status.NewInvalid(ctx, "space type is not eligible for sharing")}, nil
}
}
// do not allow share to myself or the owner if share is for a user
if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_USER &&
(utils.UserEqual(req.GetGrant().GetGrantee().GetUserId(), user.Id) || utils.UserEqual(req.GetGrant().GetGrantee().GetUserId(), sRes.GetInfo().GetOwner())) {
denySelfShare := true
// To allow adding the initial "mananger" share for the creator of a space when need to make an exception here
// if the shared resource is a space root, that does not have any Share existin yet. Note, that we have already
// verified that the user adding the share does really have "AddGrant" permissions on the affected resource, so
// this "hack" should be ok.
if isSpaceRoot {
shares, err := s.sm.ListShares(
ctx,
[]*collaboration.Filter{share.ResourceIDFilter(req.GetResourceInfo().GetId())},
)
if err != nil {
return &collaboration.CreateShareResponse{
Status: status.NewInternal(ctx, "failed to list existing shares"),
}, nil
}
if len(shares) == 0 {
denySelfShare = false
noEvent = true
}
}
if denySelfShare {
err := errtypes.BadRequest("jsoncs3: owner/creator and grantee are the same")
return nil, err
}
}
// resharing is forbidden for not space roots
if !isSpaceRoot {
// Resharing of Files/Directories is forbidden. So the grants must not allow the "grant" permissions
if HasGrantPermissions(req.GetGrant().GetPermissions().GetPermissions()) {
return &collaboration.CreateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}
}
// check if the share creator has sufficient permissions to do so.
if shareCreationAllowed := conversions.SufficientCS3Permissions(
sRes.GetInfo().GetPermissionSet(),
@@ -256,10 +313,22 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
}, nil
}
var opaque *typesv1beta1.Opaque
if isSpaceRoot {
opaque = utils.SpaceGrantOpaque()
}
if noEvent {
opaque = &typesv1beta1.Opaque{
Map: map[string]*typesv1beta1.OpaqueEntry{
"noevent": {},
},
}
}
return &collaboration.CreateShareResponse{
Status: status.NewOK(ctx),
Share: createdShare,
Opaque: utils.AppendPlainToOpaque(nil, "resourcename", sRes.GetInfo().GetName()),
Opaque: utils.AppendPlainToOpaque(opaque, "resourcename", sRes.GetInfo().GetName()),
}, nil
}
@@ -267,6 +336,30 @@ func HasGrantPermissions(p *provider.ResourcePermissions) bool {
return p.GetAddGrant() || p.GetUpdateGrant() || p.GetRemoveGrant() || p.GetDenyGrant()
}
// spaceRootHasRemainingManager returns true if the given resource has at least one share
// (excluding the share with excludeShareOpaqueID) that grants both AddGrant and RemoveGrant.
func (s *service) spaceRootHasRemainingManager(ctx context.Context, resourceID *provider.ResourceId, excludeShareOpaqueID string) (bool, error) {
shares, err := s.sm.ListShares(ctx, []*collaboration.Filter{
{
Type: collaboration.Filter_TYPE_RESOURCE_ID,
Term: &collaboration.Filter_ResourceId{ResourceId: resourceID},
},
})
if err != nil {
return false, err
}
for _, s := range shares {
if s.GetId().GetOpaqueId() == excludeShareOpaqueID {
continue
}
perms := s.GetPermissions().GetPermissions()
if perms.GetAddGrant() && perms.GetRemoveGrant() {
return true, nil
}
}
return false, nil
}
func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShareRequest) (*collaboration.RemoveShareResponse, error) {
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)
@@ -300,6 +393,20 @@ func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShar
}, err
}
// For space root shares, ensure at least one share with both AddGrant and RemoveGrant will remain
// so the space always has a manager who can administer grants.
if utils.IsSpaceRoot(sRes.GetInfo()) {
if ok, err := s.spaceRootHasRemainingManager(ctx, share.GetResourceId(), share.GetId().GetOpaqueId()); err != nil {
return &collaboration.RemoveShareResponse{
Status: status.NewInternal(ctx, "failed to list shares for space root"),
}, nil
} else if !ok {
return &collaboration.RemoveShareResponse{
Status: status.NewPermissionDenied(ctx, nil, "cannot remove the last share with manager permissions on a space root"),
}, nil
}
}
err = s.sm.Unshare(ctx, req.Ref)
if err != nil {
return &collaboration.RemoveShareResponse{
@@ -307,16 +414,20 @@ func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShar
}, nil
}
o := utils.AppendJSONToOpaque(nil, "resourceid", share.GetResourceId())
o = utils.AppendPlainToOpaque(o, "resourcename", sRes.GetInfo().GetName())
var opaque *typesv1beta1.Opaque
if utils.IsSpaceRoot(sRes.GetInfo()) {
opaque = utils.SpaceGrantOpaque()
}
opaque = utils.AppendJSONToOpaque(opaque, "resourceid", share.GetResourceId())
opaque = utils.AppendPlainToOpaque(opaque, "resourcename", sRes.GetInfo().GetName())
if user := share.GetGrantee().GetUserId(); user != nil {
o = utils.AppendJSONToOpaque(o, "granteeuserid", user)
opaque = utils.AppendJSONToOpaque(opaque, "granteeuserid", user)
} else {
o = utils.AppendJSONToOpaque(o, "granteegroupid", share.GetGrantee().GetGroupId())
opaque = utils.AppendJSONToOpaque(opaque, "granteegroupid", share.GetGrantee().GetGroupId())
}
return &collaboration.RemoveShareResponse{
Opaque: o,
Opaque: opaque,
Status: status.NewOK(ctx),
}, nil
}
@@ -361,13 +472,6 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)
// Grants must not allow grant permissions
if HasGrantPermissions(req.GetShare().GetPermissions().GetPermissions()) {
return &collaboration.UpdateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
@@ -427,6 +531,15 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar
}, err
}
// resharing is forbidden for not space roots
if !utils.IsSpaceRoot(sRes.GetInfo()) {
// Resharing of Files/Directories is forbidden. So the grants must not allow the "grant" permissions
if HasGrantPermissions(req.GetShare().GetPermissions().GetPermissions()) {
return &collaboration.UpdateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}
}
// If this is a permissions update, check if user's permissions on the resource are sufficient to set the desired permissions
var newPermissions *provider.ResourcePermissions
if slices.Contains(req.GetUpdateMask().GetPaths(), _fieldMaskPathPermissions) {
@@ -440,6 +553,20 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar
}, nil
}
// For space root shares, if the new permissions would strip AddGrant or RemoveGrant from this share,
// ensure at least one other share still has both so the space retains a manager.
if utils.IsSpaceRoot(sRes.GetInfo()) && newPermissions != nil && (!newPermissions.GetAddGrant() || !newPermissions.GetRemoveGrant()) {
if ok, err := s.spaceRootHasRemainingManager(ctx, currentShare.GetResourceId(), currentShare.GetId().GetOpaqueId()); err != nil {
return &collaboration.UpdateShareResponse{
Status: status.NewInternal(ctx, "failed to list shares for space root"),
}, nil
} else if !ok {
return &collaboration.UpdateShareResponse{
Status: status.NewPermissionDenied(ctx, nil, "cannot remove the last share with manager permissions on a space root"),
}, nil
}
}
// check if the requested permission are plausible for the Resource
// do we need more here?
if sRes.GetInfo().GetType() == provider.ResourceType_RESOURCE_TYPE_FILE {
@@ -457,10 +584,15 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar
}, nil
}
var opaque *typesv1beta1.Opaque
if utils.IsSpaceRoot(sRes.GetInfo()) {
opaque = utils.SpaceGrantOpaque()
}
res := &collaboration.UpdateShareResponse{
Status: status.NewOK(ctx),
Share: share,
Opaque: utils.AppendPlainToOpaque(nil, "resourcename", sRes.GetInfo().GetName()),
Opaque: utils.AppendPlainToOpaque(opaque, "resourcename", sRes.GetInfo().GetName()),
}
return res, nil
}
@@ -179,6 +179,10 @@ func (h *Handler) UpdateReceivedShare(w http.ResponseWriter, r *http.Request) {
response.WriteOCSSuccess(w, r, []*conversions.ShareData{data})
}
func (h *Handler) ReceivedShareNotFound(w http.ResponseWriter, r *http.Request) {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil)
}
func (h *Handler) updateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *fieldmaskpb.FieldMask) (*conversions.ShareData, response.Meta, error) {
logger := appctx.GetLogger(ctx)
@@ -78,7 +78,6 @@ var (
type Handler struct {
gatewayAddr string
machineAuthAPIKey string
storageRegistryAddr string
publicURL string
sharePrefix string
homeNamespace string
@@ -129,7 +128,6 @@ type GatewayClientGetter func() (gateway.GatewayAPIClient, error)
func (h *Handler) Init(c *config.Config) error {
h.gatewayAddr = c.GatewaySvc
h.machineAuthAPIKey = c.MachineAuthAPIKey
h.storageRegistryAddr = c.StorageregistrySvc
h.publicURL = c.Config.Host
h.sharePrefix = c.SharePrefix
h.homeNamespace = c.HomeNamespace
@@ -941,12 +939,11 @@ func (h *Handler) RemoveShare(w http.ResponseWriter, r *http.Request) {
h.removeFederatedShare(w, r, shareID)
return
}
if prov, ok := h.isSpaceShare(r, shareID); ok {
// The request is a remove space member request.
h.removeSpaceMember(w, r, shareID, prov)
if h.isSpaceShare(r, shareID) {
h.removeSpaceMember(w, r, shareID)
return
}
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil)
}
@@ -29,18 +29,12 @@ import (
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaborationv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocs/response"
"github.com/opencloud-eu/reva/v2/pkg/appctx"
"github.com/opencloud-eu/reva/v2/pkg/conversions"
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
sdk "github.com/opencloud-eu/reva/v2/pkg/sdk/common"
"github.com/opencloud-eu/reva/v2/pkg/storagespace"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/pkg/errors"
"google.golang.org/protobuf/types/known/fieldmaskpb"
)
@@ -131,45 +125,34 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p
fieldmask = append(fieldmask, "expiration")
}
ref := provider.Reference{ResourceId: info.GetId()}
p, err := h.findProvider(ctx, &ref)
if err != nil {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider", err)
lsRes, err := client.ListShares(ctx, &collaborationv1beta1.ListSharesRequest{
Filters: []*collaborationv1beta1.Filter{
{
Type: collaborationv1beta1.Filter_TYPE_RESOURCE_ID,
Term: &collaborationv1beta1.Filter_ResourceId{
ResourceId: info.GetId(),
},
},
},
})
if err != nil || lsRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error listing space members", err)
return
}
providerClient, err := h.getStorageProviderClient(p)
if err != nil {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider client", err)
return
}
lgRes, err := providerClient.ListGrants(ctx, &provider.ListGrantsRequest{Ref: &ref})
if err != nil || lgRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error listing space grants", err)
return
}
if !isSpaceManagerRemaining(lgRes.Grants, &grantee) {
if !isSpaceManagerRemainingInShares(lsRes.Shares, &grantee) {
response.WriteOCSError(w, r, http.StatusForbidden, "the space must have at least one manager", nil)
return
}
// we have to send the update request to the gateway to give it a chance to invalidate its cache
// TODO the gateway no longer should cache stuff because invalidation is to expensive. The decomposedfs already has a better cache.
if granteeExists(lgRes.Grants, &grantee) {
if existingShare := findShareByGrantee(lsRes.Shares, &grantee); existingShare != nil {
if permissions != nil {
fieldmask = append(fieldmask, "permissions")
}
updateShareReq := &collaborationv1beta1.UpdateShareRequest{
// TODO: change CS3 APIs
Opaque: &types.Opaque{
Map: map[string]*types.OpaqueEntry{
"spacegrant": {},
},
},
Opaque: utils.AppendPlainToOpaque(nil, "spacetype", info.GetSpace().GetSpaceType()),
Share: &collaborationv1beta1.Share{
ResourceId: ref.GetResourceId(),
Id: existingShare.Id,
Permissions: &collaborationv1beta1.SharePermissions{
Permissions: permissions,
},
@@ -180,10 +163,9 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p
Paths: fieldmask,
},
}
updateShareReq.Opaque = utils.AppendPlainToOpaque(updateShareReq.Opaque, "spacetype", info.GetSpace().GetSpaceType())
updateShareRes, err := client.UpdateShare(ctx, updateShareReq)
if err != nil || updateShareRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not update space member grant", err)
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not update space member", err)
return
}
} else {
@@ -198,7 +180,7 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p
},
})
if err != nil || createShareRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not add space member grant", err)
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not add space member", err)
return
}
}
@@ -206,21 +188,22 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p
response.WriteOCSSuccess(w, r, nil)
}
func (h *Handler) isSpaceShare(r *http.Request, spaceID string) (*registry.ProviderInfo, bool) {
ref, err := storagespace.ParseReference(spaceID)
if err != nil {
return nil, false
func (h *Handler) isSpaceShare(r *http.Request, shareID string) bool {
ref, err := storagespace.ParseReference(shareID)
// NOTE: we ignore the 'Path' part of the reference here as we're just interested in the space root
switch {
case err != nil:
return false
case ref.GetResourceId().GetSpaceId() == "":
return false
case ref.GetResourceId().GetOpaqueId() == "" || ref.GetResourceId().GetSpaceId() == ref.GetResourceId().GetOpaqueId():
return true
default:
return false
}
if ref.ResourceId.OpaqueId == "" {
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
}
p, err := h.findProvider(r.Context(), &ref)
return p, err == nil
}
func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string, prov *registry.ProviderInfo) {
func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spaceID string) {
ctx := r.Context()
shareWith := r.URL.Query().Get("shareWith")
@@ -245,129 +228,73 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
}
providerClient, err := h.getStorageProviderClient(prov)
if err != nil {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting storage provider client", err)
return
}
lgRes, err := providerClient.ListGrants(ctx, &provider.ListGrantsRequest{Ref: &ref})
if err != nil || lgRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error listing space grants", err)
return
}
if len(lgRes.Grants) == 1 || !isSpaceManagerRemaining(lgRes.Grants, &grantee) {
response.WriteOCSError(w, r, http.StatusForbidden, "can't remove the last manager", nil)
return
}
gatewayClient, err := h.getClient()
client, err := h.getClient()
if err != nil {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "error getting gateway client", err)
return
}
removeShareRes, err := gatewayClient.RemoveShare(ctx, &collaborationv1beta1.RemoveShareRequest{
Ref: &collaborationv1beta1.ShareReference{
Spec: &collaborationv1beta1.ShareReference_Key{
Key: &collaborationv1beta1.ShareKey{
lsRes, err := client.ListShares(ctx, &collaborationv1beta1.ListSharesRequest{
Filters: []*collaborationv1beta1.Filter{
{
Type: collaborationv1beta1.Filter_TYPE_RESOURCE_ID,
Term: &collaborationv1beta1.Filter_ResourceId{
ResourceId: ref.ResourceId,
Grantee: &grantee,
},
},
},
})
if err != nil || lsRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error listing space members", err)
return
}
if len(lsRes.Shares) == 1 || !isSpaceManagerRemainingInShares(lsRes.Shares, &grantee) {
response.WriteOCSError(w, r, http.StatusForbidden, "can't remove the last manager", nil)
return
}
s := findShareByGrantee(lsRes.Shares, &grantee)
if s == nil {
response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "cannot find share", nil)
return
}
removeShareRes, err := client.RemoveShare(ctx, &collaborationv1beta1.RemoveShareRequest{
Ref: &collaborationv1beta1.ShareReference{
Spec: &collaborationv1beta1.ShareReference_Id{
Id: s.Id,
},
},
})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error removing grant", err)
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error removing space member", err)
return
}
if removeShareRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error removing grant", err)
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error removing space member", nil)
return
}
response.WriteOCSSuccess(w, r, nil)
}
func (h *Handler) getStorageProviderClient(p *registry.ProviderInfo) (provider.ProviderAPIClient, error) {
c, err := pool.GetStorageProviderServiceClient(p.Address)
if err != nil {
err = errors.Wrap(err, "shares spaces: error getting a storage provider client")
return nil, err
}
return c, nil
}
func (h *Handler) findProvider(ctx context.Context, ref *provider.Reference) (*registry.ProviderInfo, error) {
c, err := pool.GetStorageRegistryClient(h.storageRegistryAddr)
if err != nil {
return nil, errors.Wrap(err, "shares spaces: error getting storage registry client")
}
filters := map[string]string{}
if ref.Path != "" {
filters["path"] = ref.Path
}
if ref.ResourceId != nil {
filters["storage_id"] = ref.ResourceId.StorageId
filters["space_id"] = ref.ResourceId.SpaceId
filters["opaque_id"] = ref.ResourceId.OpaqueId
}
listReq := &registry.ListStorageProvidersRequest{
Opaque: &types.Opaque{},
}
sdk.EncodeOpaqueMap(listReq.Opaque, filters)
res, err := c.ListStorageProviders(ctx, listReq)
if err != nil {
return nil, errors.Wrap(err, "shares spaces: error calling ListStorageProviders")
}
if res.Status.Code != rpc.Code_CODE_OK {
switch res.Status.Code {
case rpc.Code_CODE_NOT_FOUND:
return nil, errtypes.NotFound("shares spaces: storage provider not found for reference:" + ref.String())
case rpc.Code_CODE_PERMISSION_DENIED:
return nil, errtypes.PermissionDenied("shares spaces: " + res.Status.Message + " for " + ref.String() + " with code " + res.Status.Code.String())
case rpc.Code_CODE_INVALID_ARGUMENT, rpc.Code_CODE_FAILED_PRECONDITION, rpc.Code_CODE_OUT_OF_RANGE:
return nil, errtypes.BadRequest("shares spaces: " + res.Status.Message + " for " + ref.String() + " with code " + res.Status.Code.String())
case rpc.Code_CODE_UNIMPLEMENTED:
return nil, errtypes.NotSupported("shares spaces: " + res.Status.Message + " for " + ref.String() + " with code " + res.Status.Code.String())
default:
return nil, status.NewErrorFromCode(res.Status.Code, "shares spaces")
}
}
if len(res.Providers) < 1 {
return nil, errtypes.NotFound("shares spaces: no provider found")
}
return res.Providers[0], nil
}
func isSpaceManagerRemaining(grants []*provider.Grant, grantee *provider.Grantee) bool {
for _, g := range grants {
// RemoveGrant is currently the way to check for the manager role
// If it is not set than the current grant is not for a manager and
// we can just continue with the next one.
if g.Permissions.RemoveGrant && !isEqualGrantee(g.Grantee, grantee) {
func isSpaceManagerRemainingInShares(shares []*collaborationv1beta1.Share, grantee *provider.Grantee) bool {
for _, s := range shares {
if s.GetPermissions().GetPermissions().GetRemoveGrant() && !isEqualGrantee(s.Grantee, grantee) {
return true
}
}
return false
}
func granteeExists(grants []*provider.Grant, grantee *provider.Grantee) bool {
for _, g := range grants {
if isEqualGrantee(g.Grantee, grantee) {
return true
func findShareByGrantee(shares []*collaborationv1beta1.Share, grantee *provider.Grantee) *collaborationv1beta1.Share {
for _, s := range shares {
if isEqualGrantee(s.Grantee, grantee) {
return s
}
}
return false
return nil
}
func isEqualGrantee(a, b *provider.Grantee) bool {
@@ -34,6 +34,7 @@ import (
ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx"
"github.com/opencloud-eu/reva/v2/pkg/permission"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/share"
"github.com/opencloud-eu/reva/v2/pkg/utils"
)
@@ -330,7 +331,7 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filte
log := appctx.GetLogger(ctx)
lsUserSharesRequest := collaboration.ListSharesRequest{
Filters: filters,
Filters: append(filters, share.SpaceRootFilter(false)),
}
ocsDataPayload := make([]*conversions.ShareData, 0)
@@ -123,6 +123,13 @@ func (s *svc) routerInit(log *zerolog.Logger) error {
r.Delete("/", sharesHandler.RejectReceivedShare)
r.Put("/", sharesHandler.UpdateReceivedShare)
})
r.Route("/pending", func(r chi.Router) {
r.Post("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
})
r.Delete("/", sharesHandler.ReceivedShareNotFound)
r.Put("/", sharesHandler.ReceivedShareNotFound)
})
r.Route("/remote_shares", func(r chi.Router) {
r.Get("/", sharesHandler.ListFederatedShares)
r.Get("/{shareid}", sharesHandler.GetFederatedShare)
@@ -296,16 +296,6 @@ func (m *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
user := ctxpkg.ContextMustGetUser(ctx)
ts := utils.TSNow()
// do not allow share to myself or the owner if share is for a user
// TODO: should this not already be caught at the gw level?
if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_USER &&
(utils.UserEqual(g.Grantee.GetUserId(), user.Id) || utils.UserEqual(g.Grantee.GetUserId(), md.Owner)) {
err := errtypes.BadRequest("jsoncs3: owner/creator and grantee are the same")
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return nil, err
}
// check if share already exists.
key := &collaboration.ShareKey{
// Owner: md.Owner, owner no longer matters as it belongs to the space
@@ -508,17 +498,10 @@ func (m *Manager) Unshare(ctx context.Context, ref *collaboration.ShareReference
return err
}
user := ctxpkg.ContextMustGetUser(ctx)
s, err := m.get(ctx, ref)
if err != nil {
return err
}
// TODO allow manager to unshare shares in a space created by other users
if !share.IsCreatedByUser(s, user) {
// TODO why not permission denied?
return errtypes.NotFound(ref.String())
}
return m.removeShare(ctx, s, false)
}
@@ -82,11 +82,6 @@ func (m *manager) Share(ctx context.Context, md *provider.ResourceInfo, g *colla
Nanos: uint32(now % 1000000000),
}
if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_USER &&
(utils.UserEqual(g.Grantee.GetUserId(), user.Id) || utils.UserEqual(g.Grantee.GetUserId(), md.Owner)) {
return nil, errtypes.BadRequest("memory: owner/creator and grantee are the same")
}
// check if share already exists.
key := &collaboration.ShareKey{
Owner: md.Owner,
+15
View File
@@ -136,6 +136,18 @@ func StateFilter(state collaboration.ShareState) *collaboration.Filter {
}
}
// SpaceRootFilter is an abstraction for filtering shares by whether the shared
// resource is a space root. Pass true to include only space-root shares (space
// membership), false to exclude them (file/folder shares only).
func SpaceRootFilter(spaceRoot bool) *collaboration.Filter {
return &collaboration.Filter{
Type: collaboration.Filter_TYPE_SPACE_ROOT,
Term: &collaboration.Filter_SpaceRoot{
SpaceRoot: spaceRoot,
},
}
}
// IsCreatedByUser checks if the user is the owner or creator of the share.
func IsCreatedByUser(share *collaboration.Share, user *userv1beta1.User) bool {
return utils.UserEqual(user.Id, share.Owner) || utils.UserEqual(user.Id, share.Creator)
@@ -172,6 +184,9 @@ func MatchesFilter(share *collaboration.Share, state collaboration.ShareState, f
return share.ResourceId.SpaceId == filter.GetSpaceId()
case collaboration.Filter_TYPE_STATE:
return state == filter.GetState()
case collaboration.Filter_TYPE_SPACE_ROOT:
isSpaceRoot := share.ResourceId.SpaceId == share.ResourceId.OpaqueId
return isSpaceRoot == filter.GetSpaceRoot()
default:
return false
}
+1 -1
View File
@@ -35,7 +35,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/cache")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/cache")
}
// NewStatCache creates a new StatCache
@@ -53,7 +53,7 @@ var _spaceTypePersonal = "personal"
var _spaceTypeProject = "project"
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/lookup")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/pkg/decomposedfs/lookup")
}
// IDCache is a cache for node ids
@@ -50,7 +50,7 @@ var (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/trashbin")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/fs/posix/trashbin")
}
type Trashbin struct {
@@ -29,12 +29,11 @@ import (
"strings"
"time"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/watcher"
"github.com/pablodz/inotifywaitgo/inotifywaitgo"
"github.com/rs/zerolog"
slogzerolog "github.com/samber/slog-zerolog/v2"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/watcher"
)
type InotifyWatcher struct {
@@ -43,7 +42,7 @@ type InotifyWatcher struct {
log *zerolog.Logger
}
func NewWatcher(tree *Tree, o *options.Options, log *zerolog.Logger) (*InotifyWatcher, error) {
func NewInotifyWatcher(tree *Tree, o *options.Options, log *zerolog.Logger) (*InotifyWatcher, error) {
return &InotifyWatcher{
tree: tree,
options: o,
@@ -0,0 +1,23 @@
//go:build !linux
// Copyright 2025 OpenCloud GmbH <mail@opencloud.eu>
// SPDX-License-Identifier: Apache-2.0
package tree
import (
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
"github.com/rs/zerolog"
)
// NullWatcher is a dummy watcher that does nothing
type NullWatcher struct{}
// Watch does nothing
func (*NullWatcher) Watch(path string) {}
// NewInotifyWatcher returns a new inotify watcher
func NewInotifyWatcher(_ *Tree, _ *options.Options, _ *zerolog.Logger) (*NullWatcher, error) {
return nil, errtypes.NotSupported("inotify watcher is not supported on this platform")
}
+2 -14
View File
@@ -68,7 +68,7 @@ var (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/tree")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/pkg/decomposedfs/tree")
}
type Watcher interface {
@@ -160,7 +160,7 @@ func New(lu node.PathLookup, bs node.Blobstore, um usermapper.Mapper, trashbin *
return nil, err
}
default:
t.watcher, err = NewWatcher(t, o, log)
t.watcher, err = NewInotifyWatcher(t, o, log)
if err != nil {
return nil, err
}
@@ -360,9 +360,6 @@ func (t *Tree) CreateDir(ctx context.Context, n *node.Node) (err error) {
// Move replaces the target with the source
func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node) (err error) {
ctx, span := tracer.Start(ctx, "Move")
defer span.End()
if oldNode.SpaceID != newNode.SpaceID {
// WebDAV RFC https://www.rfc-editor.org/rfc/rfc4918#section-9.9.4 says to use
// > 502 (Bad Gateway) - This may occur when the destination is on another
@@ -385,7 +382,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
newNode.ID = oldNode.ID
}
_, subspan := tracer.Start(ctx, "os.Rename")
// rename node
err = os.Rename(
filepath.Join(oldParent, oldNode.Name),
@@ -394,9 +390,7 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
if err != nil {
return errors.Wrap(err, "posixfs: could not move child")
}
subspan.End()
_, subspan = tracer.Start(ctx, "update id cache and attributes")
// update the id cache
// invalidate old tree
err = t.lookup.IDCache.DeleteByPath(ctx, filepath.Join(oldNode.ParentPath(), oldNode.Name))
@@ -415,9 +409,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
return errors.Wrap(err, "posixfs: could not update node attributes")
}
subspan.End()
_, subspan = tracer.Start(ctx, "warmup id cache for moved subtree")
// update id cache for the moved subtree.
if oldNode.IsDir(ctx) {
err = t.WarmupIDCache(filepath.Join(newNode.ParentPath(), newNode.Name), false, false)
@@ -425,7 +416,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
return err
}
}
subspan.End()
// the size diff is the current treesize or blobsize of the old/source node
var sizeDiff int64
@@ -439,7 +429,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
sizeDiff = oldNode.Blobsize
}
_, subspan = tracer.Start(ctx, "propagate size changes")
err = t.Propagate(ctx, oldNode, -sizeDiff)
if err != nil {
return errors.Wrap(err, "posixfs: Move: could not propagate old node")
@@ -448,7 +437,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
if err != nil {
return errors.Wrap(err, "posixfs: Move: could not propagate new node")
}
subspan.End()
return nil
}
@@ -1,13 +0,0 @@
package tree
import (
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
)
var ErrUnsupportedWatcher = errtypes.NotSupported("watching the filesystem is not supported on this platform")
// NoopWatcher is a watcher that does nothing
type NoopWatcher struct{}
// Watch does nothing
func (*NoopWatcher) Watch(_ string) {}
@@ -1,226 +0,0 @@
//go:build darwin && experimental_watchfs_darwin
package tree
import (
"io/fs"
"os"
"path/filepath"
"strings"
"sync"
"github.com/fsnotify/fsnotify"
"github.com/rs/zerolog"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/watcher"
)
// FSnotifyWatcher fills the gap with fsnotify on Darwin, be careful with its limitations.
// The main reason for its existence is to provide a working watcher on Darwin for development and testing purposes.
type FSnotifyWatcher struct {
tree *Tree
options *options.Options
log *zerolog.Logger
mu sync.Mutex
watched map[string]struct{}
}
// NewWatcher creates a new FSnotifyWatcher which implements the Watcher interface for Darwin using fsnotify.
func NewWatcher(tree *Tree, o *options.Options, log *zerolog.Logger) (*FSnotifyWatcher, error) {
log.Warn().Msg("fsnotify watcher on darwin has limitations and may not work as expected in all scenarios, not recommended for production use")
return &FSnotifyWatcher{
tree: tree,
options: o,
log: log,
watched: make(map[string]struct{}),
}, nil
}
// add takes care of adding watches for root and its subpaths.
func (w *FSnotifyWatcher) add(fsWatcher *fsnotify.Watcher, root string) error {
// Check if the root is ignored before walking the tree
if isPathIgnored(w.tree, root) {
return nil
}
return filepath.WalkDir(root, func(p string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
// skip ignored paths or files
if isPathIgnored(w.tree, p) || !d.IsDir() {
return nil
}
w.mu.Lock()
defer w.mu.Unlock()
// path is known, skip
if _, ok := w.watched[p]; ok {
return nil
}
if err := fsWatcher.Add(p); err != nil {
return err
}
w.watched[p] = struct{}{}
return nil
})
}
// remove takes care of removing watches for root and its subpaths.
func (w *FSnotifyWatcher) remove(fsWatcher *fsnotify.Watcher, root string) {
w.mu.Lock()
defer w.mu.Unlock()
for p := range w.watched {
if p == root || isSubpath(root, p) {
if err := fsWatcher.Remove(p); err != nil {
w.log.Debug().Err(err).Str("path", p).Msg("failed to remove watch")
}
delete(w.watched, p)
}
}
}
// handleEvent supervises the handling of fsnotify events.
func (w *FSnotifyWatcher) handleEvent(fsWatcher *fsnotify.Watcher, event fsnotify.Event) error {
isCreate := event.Op&fsnotify.Create != 0
isRemove := event.Op&fsnotify.Remove != 0
isRename := event.Op&fsnotify.Rename != 0
isWrite := event.Op&fsnotify.Write != 0
isKnownEvent := isCreate || isRemove || isRename || isWrite
isIgnored := isPathIgnored(w.tree, event.Name)
// filter out unwanted events
if isIgnored || !isKnownEvent {
return nil
}
st, statErr := os.Stat(event.Name)
exists := statErr == nil
isDir := exists && st.IsDir()
switch {
case isRename:
if exists {
if isDir {
_ = w.add(fsWatcher, event.Name)
}
return w.tree.Scan(event.Name, watcher.ActionMove, isDir)
}
w.remove(fsWatcher, event.Name)
return w.tree.Scan(event.Name, watcher.ActionMoveFrom, false)
case isRemove:
w.remove(fsWatcher, event.Name)
return w.tree.Scan(event.Name, watcher.ActionDelete, false)
case isCreate:
if exists {
if isDir {
_ = w.add(fsWatcher, event.Name)
}
return w.tree.Scan(event.Name, watcher.ActionCreate, isDir)
}
w.remove(fsWatcher, event.Name)
return w.tree.Scan(event.Name, watcher.ActionMoveFrom, false)
case isWrite:
if exists {
return w.tree.Scan(event.Name, watcher.ActionUpdate, isDir)
}
default:
w.log.Warn().Interface("event", event).Msg("unhandled event")
}
return nil
}
// Watch starts watching the given path for changes.
func (w *FSnotifyWatcher) Watch(path string) {
fsWatcher, err := fsnotify.NewWatcher()
if err != nil {
w.log.Error().Err(err).Msg("failed to create watcher")
return
}
defer func() { _ = fsWatcher.Close() }()
if w.options.InotifyStatsFrequency > 0 {
w.log.Debug().Str("watcher", "not implemented on darwin").Msg("fsnotify stats")
}
go func() {
for {
select {
case event, ok := <-fsWatcher.Events:
if !ok {
return
}
if err := w.handleEvent(fsWatcher, event); err != nil {
w.log.Error().Err(err).Str("path", event.Name).Msg("error scanning file")
}
case err, ok := <-fsWatcher.Errors:
if !ok {
return
}
w.log.Error().Err(err).Msg("fsnotify error")
}
}
}()
base := filepath.Join(path, "users")
if err := w.add(fsWatcher, base); err != nil {
w.log.Error().Err(err).Str("path", base).Msg("failed to add initial watches")
}
<-make(chan struct{})
}
// isSubpath checks if p is a subpath of root
func isSubpath(root, p string) bool {
r, err := filepath.Abs(root)
if err != nil {
r = filepath.Clean(root)
}
pp, err := filepath.Abs(p)
if err != nil {
pp = filepath.Clean(p)
}
rel, err := filepath.Rel(r, pp)
if err != nil {
return false
}
return rel != "." && !strings.HasPrefix(rel, "..")
}
// isIgnored checks if the path is ignored by its tree.
func isPathIgnored(tree *Tree, path string) bool {
isLockFile := isLockFile(path)
isTrash := isTrash(path)
isUpload := tree.isUpload(path)
isInternal := tree.isInternal(path)
// ask the tree if the path is internal or ignored
return path == "" ||
isLockFile ||
isTrash ||
isUpload ||
isInternal
}
@@ -1,17 +0,0 @@
//go:build !linux && (!darwin || !experimental_watchfs_darwin)
// Copyright 2025 OpenCloud GmbH <mail@opencloud.eu>
// SPDX-License-Identifier: Apache-2.0
package tree
import (
"github.com/rs/zerolog"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/options"
)
// NewWatcher returns a NoopWatcher on unsupported platforms
func NewWatcher(_ *Tree, _ *options.Options, _ *zerolog.Logger) (*NoopWatcher, error) {
return nil, ErrUnsupportedWatcher
}
@@ -86,7 +86,7 @@ var (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/pkg/decomposedfs")
}
// Session is the interface that DecomposedfsSession implements. By combining tus.Upload,
@@ -48,7 +48,7 @@ const (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/lookup")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/lookup")
}
// Lookup implements transformations from filepath to node and back
@@ -153,10 +153,6 @@ func (b HybridBackend) getAll(ctx context.Context, n MetadataNode, skipCache, sk
}
if len(attrNames) == 0 {
err = b.metaCache.PushToCache(b.cacheKey(n), attribs)
if err != nil {
return nil, err
}
return attribs, nil
}
@@ -183,9 +179,6 @@ func (b HybridBackend) getAll(ctx context.Context, n MetadataNode, skipCache, sk
// merge the attributes from the offload file
offloaded, err := xattr.Get(path, _metadataOffloadedAttr)
if err != nil && !IsAttrUnset(err) {
return nil, err
}
if !skipOffloaded && err == nil && string(offloaded) == "1" {
msgpackAttribs := map[string][]byte{}
msgBytes, err := os.ReadFile(b.MetadataPath(n))
@@ -315,9 +308,16 @@ func (b HybridBackend) SetMultiple(ctx context.Context, n MetadataNode, attribs
return fmt.Errorf("failed to set %d/%d xattrs: %w", xerrs, total, xerr)
}
// Update the cache with the new values
_, err = b.getAll(ctx, n, true, false, false)
return err
attribs, err = b.getAll(ctx, n, true, false, false)
if err != nil {
return err
}
err = b.metaCache.PushToCache(b.cacheKey(n), attribs)
if err != nil {
return err
}
return nil
}
func (b HybridBackend) offloadMetadata(ctx context.Context, n MetadataNode) error {
@@ -439,9 +439,11 @@ func (b HybridBackend) Remove(ctx context.Context, n MetadataNode, key string, a
}
}
// Update the cache with the new values
_, err := b.getAll(ctx, n, true, false, false)
return err
attribs, err := b.getAll(ctx, n, true, false, false)
if err != nil {
return err
}
return b.metaCache.PushToCache(b.cacheKey(n), attribs)
}
// IsMetaFile returns whether the given path represents a meta file
@@ -453,10 +455,15 @@ func (b HybridBackend) Purge(ctx context.Context, n MetadataNode) error {
_, err := os.Stat(path)
if err == nil {
attribs, err := b.getAll(ctx, n, true, false, true)
if err == nil {
for attr := range attribs {
if strings.HasPrefix(attr, prefixes.OcPrefix) {
_ = xattr.Remove(path, attr)
if err != nil {
return err
}
for attr := range attribs {
if strings.HasPrefix(attr, prefixes.OcPrefix) {
err := xattr.Remove(path, attr)
if err != nil {
return err
}
}
}
@@ -31,7 +31,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/metadata")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/metadata")
}
var errUnconfiguredError = errors.New("no metadata backend configured. Bailing out")
@@ -58,7 +58,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/node")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node")
}
// Define keys and values used in the node metadata
@@ -21,7 +21,7 @@ var (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/permissions")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/permissions")
}
const (
@@ -38,7 +38,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/tree/propagator")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/tree/propagator")
}
type Propagator interface {
@@ -53,7 +53,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/tree")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/tree")
}
// Tree manages a hierarchical tree
@@ -57,7 +57,7 @@ var (
)
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/decomposedfs/upload")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/upload")
}
// WriteChunk writes the stream from the reader to the given offset of the upload
+1 -1
View File
@@ -49,7 +49,7 @@ import (
var tracer trace.Tracer
func init() {
tracer = otel.Tracer("github.com/opencloud-eu/reva/v2/pkg/storage/utils/metadata")
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/metadata")
}
// CS3 represents a metadata storage with a cs3 storage backend
+10
View File
@@ -470,6 +470,16 @@ func ExistsInOpaque(o *types.Opaque, key string) bool {
return ok
}
// SpaceGrantOpaque returns an Opaque with the "spacegrant" key set, which
// signals to storage and event middleware that a grant targets a space root.
func SpaceGrantOpaque() *types.Opaque {
return &types.Opaque{
Map: map[string]*types.OpaqueEntry{
"spacegrant": {},
},
}
}
// MergeOpaques will merge the opaques. If a key exists in both opaques
// the values from the first opaque will be taken
func MergeOpaques(o *types.Opaque, p *types.Opaque) *types.Opaque {
@@ -0,0 +1,350 @@
// Copyright 2018-2022 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.
// Code generated by mockery v2.53.2. DO NOT EDIT.
package mocks
import (
context "context"
grpc "google.golang.org/grpc"
mock "github.com/stretchr/testify/mock"
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
)
// SpacesAPIClient is an autogenerated mock type for the SpacesAPIClient type
type SpacesAPIClient struct {
mock.Mock
}
type SpacesAPIClient_Expecter struct {
mock *mock.Mock
}
func (_m *SpacesAPIClient) EXPECT() *SpacesAPIClient_Expecter {
return &SpacesAPIClient_Expecter{mock: &_m.Mock}
}
// CreateStorageSpace provides a mock function with given fields: ctx, in, opts
func (_m *SpacesAPIClient) CreateStorageSpace(ctx context.Context, in *providerv1beta1.CreateStorageSpaceRequest, opts ...grpc.CallOption) (*providerv1beta1.CreateStorageSpaceResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for CreateStorageSpace")
}
var r0 *providerv1beta1.CreateStorageSpaceResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.CreateStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.CreateStorageSpaceResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.CreateStorageSpaceRequest, ...grpc.CallOption) *providerv1beta1.CreateStorageSpaceResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*providerv1beta1.CreateStorageSpaceResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.CreateStorageSpaceRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SpacesAPIClient_CreateStorageSpace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateStorageSpace'
type SpacesAPIClient_CreateStorageSpace_Call struct {
*mock.Call
}
// CreateStorageSpace is a helper method to define mock.On call
// - ctx context.Context
// - in *providerv1beta1.CreateStorageSpaceRequest
// - opts ...grpc.CallOption
func (_e *SpacesAPIClient_Expecter) CreateStorageSpace(ctx interface{}, in interface{}, opts ...interface{}) *SpacesAPIClient_CreateStorageSpace_Call {
return &SpacesAPIClient_CreateStorageSpace_Call{Call: _e.mock.On("CreateStorageSpace",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *SpacesAPIClient_CreateStorageSpace_Call) Run(run func(ctx context.Context, in *providerv1beta1.CreateStorageSpaceRequest, opts ...grpc.CallOption)) *SpacesAPIClient_CreateStorageSpace_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*providerv1beta1.CreateStorageSpaceRequest), variadicArgs...)
})
return _c
}
func (_c *SpacesAPIClient_CreateStorageSpace_Call) Return(_a0 *providerv1beta1.CreateStorageSpaceResponse, _a1 error) *SpacesAPIClient_CreateStorageSpace_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *SpacesAPIClient_CreateStorageSpace_Call) RunAndReturn(run func(context.Context, *providerv1beta1.CreateStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.CreateStorageSpaceResponse, error)) *SpacesAPIClient_CreateStorageSpace_Call {
_c.Call.Return(run)
return _c
}
// DeleteStorageSpace provides a mock function with given fields: ctx, in, opts
func (_m *SpacesAPIClient) DeleteStorageSpace(ctx context.Context, in *providerv1beta1.DeleteStorageSpaceRequest, opts ...grpc.CallOption) (*providerv1beta1.DeleteStorageSpaceResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for DeleteStorageSpace")
}
var r0 *providerv1beta1.DeleteStorageSpaceResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.DeleteStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.DeleteStorageSpaceResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.DeleteStorageSpaceRequest, ...grpc.CallOption) *providerv1beta1.DeleteStorageSpaceResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*providerv1beta1.DeleteStorageSpaceResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.DeleteStorageSpaceRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SpacesAPIClient_DeleteStorageSpace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteStorageSpace'
type SpacesAPIClient_DeleteStorageSpace_Call struct {
*mock.Call
}
// DeleteStorageSpace is a helper method to define mock.On call
// - ctx context.Context
// - in *providerv1beta1.DeleteStorageSpaceRequest
// - opts ...grpc.CallOption
func (_e *SpacesAPIClient_Expecter) DeleteStorageSpace(ctx interface{}, in interface{}, opts ...interface{}) *SpacesAPIClient_DeleteStorageSpace_Call {
return &SpacesAPIClient_DeleteStorageSpace_Call{Call: _e.mock.On("DeleteStorageSpace",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *SpacesAPIClient_DeleteStorageSpace_Call) Run(run func(ctx context.Context, in *providerv1beta1.DeleteStorageSpaceRequest, opts ...grpc.CallOption)) *SpacesAPIClient_DeleteStorageSpace_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*providerv1beta1.DeleteStorageSpaceRequest), variadicArgs...)
})
return _c
}
func (_c *SpacesAPIClient_DeleteStorageSpace_Call) Return(_a0 *providerv1beta1.DeleteStorageSpaceResponse, _a1 error) *SpacesAPIClient_DeleteStorageSpace_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *SpacesAPIClient_DeleteStorageSpace_Call) RunAndReturn(run func(context.Context, *providerv1beta1.DeleteStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.DeleteStorageSpaceResponse, error)) *SpacesAPIClient_DeleteStorageSpace_Call {
_c.Call.Return(run)
return _c
}
// ListStorageSpaces provides a mock function with given fields: ctx, in, opts
func (_m *SpacesAPIClient) ListStorageSpaces(ctx context.Context, in *providerv1beta1.ListStorageSpacesRequest, opts ...grpc.CallOption) (*providerv1beta1.ListStorageSpacesResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for ListStorageSpaces")
}
var r0 *providerv1beta1.ListStorageSpacesResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ListStorageSpacesRequest, ...grpc.CallOption) (*providerv1beta1.ListStorageSpacesResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ListStorageSpacesRequest, ...grpc.CallOption) *providerv1beta1.ListStorageSpacesResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*providerv1beta1.ListStorageSpacesResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.ListStorageSpacesRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SpacesAPIClient_ListStorageSpaces_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListStorageSpaces'
type SpacesAPIClient_ListStorageSpaces_Call struct {
*mock.Call
}
// ListStorageSpaces is a helper method to define mock.On call
// - ctx context.Context
// - in *providerv1beta1.ListStorageSpacesRequest
// - opts ...grpc.CallOption
func (_e *SpacesAPIClient_Expecter) ListStorageSpaces(ctx interface{}, in interface{}, opts ...interface{}) *SpacesAPIClient_ListStorageSpaces_Call {
return &SpacesAPIClient_ListStorageSpaces_Call{Call: _e.mock.On("ListStorageSpaces",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *SpacesAPIClient_ListStorageSpaces_Call) Run(run func(ctx context.Context, in *providerv1beta1.ListStorageSpacesRequest, opts ...grpc.CallOption)) *SpacesAPIClient_ListStorageSpaces_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*providerv1beta1.ListStorageSpacesRequest), variadicArgs...)
})
return _c
}
func (_c *SpacesAPIClient_ListStorageSpaces_Call) Return(_a0 *providerv1beta1.ListStorageSpacesResponse, _a1 error) *SpacesAPIClient_ListStorageSpaces_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *SpacesAPIClient_ListStorageSpaces_Call) RunAndReturn(run func(context.Context, *providerv1beta1.ListStorageSpacesRequest, ...grpc.CallOption) (*providerv1beta1.ListStorageSpacesResponse, error)) *SpacesAPIClient_ListStorageSpaces_Call {
_c.Call.Return(run)
return _c
}
// UpdateStorageSpace provides a mock function with given fields: ctx, in, opts
func (_m *SpacesAPIClient) UpdateStorageSpace(ctx context.Context, in *providerv1beta1.UpdateStorageSpaceRequest, opts ...grpc.CallOption) (*providerv1beta1.UpdateStorageSpaceResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for UpdateStorageSpace")
}
var r0 *providerv1beta1.UpdateStorageSpaceResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.UpdateStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.UpdateStorageSpaceResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.UpdateStorageSpaceRequest, ...grpc.CallOption) *providerv1beta1.UpdateStorageSpaceResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*providerv1beta1.UpdateStorageSpaceResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.UpdateStorageSpaceRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SpacesAPIClient_UpdateStorageSpace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateStorageSpace'
type SpacesAPIClient_UpdateStorageSpace_Call struct {
*mock.Call
}
// UpdateStorageSpace is a helper method to define mock.On call
// - ctx context.Context
// - in *providerv1beta1.UpdateStorageSpaceRequest
// - opts ...grpc.CallOption
func (_e *SpacesAPIClient_Expecter) UpdateStorageSpace(ctx interface{}, in interface{}, opts ...interface{}) *SpacesAPIClient_UpdateStorageSpace_Call {
return &SpacesAPIClient_UpdateStorageSpace_Call{Call: _e.mock.On("UpdateStorageSpace",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *SpacesAPIClient_UpdateStorageSpace_Call) Run(run func(ctx context.Context, in *providerv1beta1.UpdateStorageSpaceRequest, opts ...grpc.CallOption)) *SpacesAPIClient_UpdateStorageSpace_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*providerv1beta1.UpdateStorageSpaceRequest), variadicArgs...)
})
return _c
}
func (_c *SpacesAPIClient_UpdateStorageSpace_Call) Return(_a0 *providerv1beta1.UpdateStorageSpaceResponse, _a1 error) *SpacesAPIClient_UpdateStorageSpace_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *SpacesAPIClient_UpdateStorageSpace_Call) RunAndReturn(run func(context.Context, *providerv1beta1.UpdateStorageSpaceRequest, ...grpc.CallOption) (*providerv1beta1.UpdateStorageSpaceResponse, error)) *SpacesAPIClient_UpdateStorageSpace_Call {
_c.Call.Return(run)
return _c
}
// NewSpacesAPIClient creates a new instance of SpacesAPIClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewSpacesAPIClient(t interface {
mock.TestingT
Cleanup(func())
}) *SpacesAPIClient {
mock := &SpacesAPIClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
@@ -0,0 +1,277 @@
// Copyright 2018-2022 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.
// Code generated by mockery v2.53.2. DO NOT EDIT.
package mocks
import (
context "context"
grpc "google.golang.org/grpc"
mock "github.com/stretchr/testify/mock"
registryv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
)
// StorageRegistryAPIClient is an autogenerated mock type for the StorageRegistryAPIClient type
type StorageRegistryAPIClient struct {
mock.Mock
}
type StorageRegistryAPIClient_Expecter struct {
mock *mock.Mock
}
func (_m *StorageRegistryAPIClient) EXPECT() *StorageRegistryAPIClient_Expecter {
return &StorageRegistryAPIClient_Expecter{mock: &_m.Mock}
}
// GetHome provides a mock function with given fields: ctx, in, opts
func (_m *StorageRegistryAPIClient) GetHome(ctx context.Context, in *registryv1beta1.GetHomeRequest, opts ...grpc.CallOption) (*registryv1beta1.GetHomeResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for GetHome")
}
var r0 *registryv1beta1.GetHomeResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.GetHomeRequest, ...grpc.CallOption) (*registryv1beta1.GetHomeResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.GetHomeRequest, ...grpc.CallOption) *registryv1beta1.GetHomeResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*registryv1beta1.GetHomeResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *registryv1beta1.GetHomeRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// StorageRegistryAPIClient_GetHome_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetHome'
type StorageRegistryAPIClient_GetHome_Call struct {
*mock.Call
}
// GetHome is a helper method to define mock.On call
// - ctx context.Context
// - in *registryv1beta1.GetHomeRequest
// - opts ...grpc.CallOption
func (_e *StorageRegistryAPIClient_Expecter) GetHome(ctx interface{}, in interface{}, opts ...interface{}) *StorageRegistryAPIClient_GetHome_Call {
return &StorageRegistryAPIClient_GetHome_Call{Call: _e.mock.On("GetHome",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *StorageRegistryAPIClient_GetHome_Call) Run(run func(ctx context.Context, in *registryv1beta1.GetHomeRequest, opts ...grpc.CallOption)) *StorageRegistryAPIClient_GetHome_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*registryv1beta1.GetHomeRequest), variadicArgs...)
})
return _c
}
func (_c *StorageRegistryAPIClient_GetHome_Call) Return(_a0 *registryv1beta1.GetHomeResponse, _a1 error) *StorageRegistryAPIClient_GetHome_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *StorageRegistryAPIClient_GetHome_Call) RunAndReturn(run func(context.Context, *registryv1beta1.GetHomeRequest, ...grpc.CallOption) (*registryv1beta1.GetHomeResponse, error)) *StorageRegistryAPIClient_GetHome_Call {
_c.Call.Return(run)
return _c
}
// GetStorageProviders provides a mock function with given fields: ctx, in, opts
func (_m *StorageRegistryAPIClient) GetStorageProviders(ctx context.Context, in *registryv1beta1.GetStorageProvidersRequest, opts ...grpc.CallOption) (*registryv1beta1.GetStorageProvidersResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for GetStorageProviders")
}
var r0 *registryv1beta1.GetStorageProvidersResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.GetStorageProvidersRequest, ...grpc.CallOption) (*registryv1beta1.GetStorageProvidersResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.GetStorageProvidersRequest, ...grpc.CallOption) *registryv1beta1.GetStorageProvidersResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*registryv1beta1.GetStorageProvidersResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *registryv1beta1.GetStorageProvidersRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// StorageRegistryAPIClient_GetStorageProviders_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStorageProviders'
type StorageRegistryAPIClient_GetStorageProviders_Call struct {
*mock.Call
}
// GetStorageProviders is a helper method to define mock.On call
// - ctx context.Context
// - in *registryv1beta1.GetStorageProvidersRequest
// - opts ...grpc.CallOption
func (_e *StorageRegistryAPIClient_Expecter) GetStorageProviders(ctx interface{}, in interface{}, opts ...interface{}) *StorageRegistryAPIClient_GetStorageProviders_Call {
return &StorageRegistryAPIClient_GetStorageProviders_Call{Call: _e.mock.On("GetStorageProviders",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *StorageRegistryAPIClient_GetStorageProviders_Call) Run(run func(ctx context.Context, in *registryv1beta1.GetStorageProvidersRequest, opts ...grpc.CallOption)) *StorageRegistryAPIClient_GetStorageProviders_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*registryv1beta1.GetStorageProvidersRequest), variadicArgs...)
})
return _c
}
func (_c *StorageRegistryAPIClient_GetStorageProviders_Call) Return(_a0 *registryv1beta1.GetStorageProvidersResponse, _a1 error) *StorageRegistryAPIClient_GetStorageProviders_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *StorageRegistryAPIClient_GetStorageProviders_Call) RunAndReturn(run func(context.Context, *registryv1beta1.GetStorageProvidersRequest, ...grpc.CallOption) (*registryv1beta1.GetStorageProvidersResponse, error)) *StorageRegistryAPIClient_GetStorageProviders_Call {
_c.Call.Return(run)
return _c
}
// ListStorageProviders provides a mock function with given fields: ctx, in, opts
func (_m *StorageRegistryAPIClient) ListStorageProviders(ctx context.Context, in *registryv1beta1.ListStorageProvidersRequest, opts ...grpc.CallOption) (*registryv1beta1.ListStorageProvidersResponse, error) {
var tmpRet mock.Arguments
if len(opts) > 0 {
tmpRet = _m.Called(ctx, in, opts)
} else {
tmpRet = _m.Called(ctx, in)
}
ret := tmpRet
if len(ret) == 0 {
panic("no return value specified for ListStorageProviders")
}
var r0 *registryv1beta1.ListStorageProvidersResponse
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.ListStorageProvidersRequest, ...grpc.CallOption) (*registryv1beta1.ListStorageProvidersResponse, error)); ok {
return rf(ctx, in, opts...)
}
if rf, ok := ret.Get(0).(func(context.Context, *registryv1beta1.ListStorageProvidersRequest, ...grpc.CallOption) *registryv1beta1.ListStorageProvidersResponse); ok {
r0 = rf(ctx, in, opts...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*registryv1beta1.ListStorageProvidersResponse)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *registryv1beta1.ListStorageProvidersRequest, ...grpc.CallOption) error); ok {
r1 = rf(ctx, in, opts...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// StorageRegistryAPIClient_ListStorageProviders_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListStorageProviders'
type StorageRegistryAPIClient_ListStorageProviders_Call struct {
*mock.Call
}
// ListStorageProviders is a helper method to define mock.On call
// - ctx context.Context
// - in *registryv1beta1.ListStorageProvidersRequest
// - opts ...grpc.CallOption
func (_e *StorageRegistryAPIClient_Expecter) ListStorageProviders(ctx interface{}, in interface{}, opts ...interface{}) *StorageRegistryAPIClient_ListStorageProviders_Call {
return &StorageRegistryAPIClient_ListStorageProviders_Call{Call: _e.mock.On("ListStorageProviders",
append([]interface{}{ctx, in}, opts...)...)}
}
func (_c *StorageRegistryAPIClient_ListStorageProviders_Call) Run(run func(ctx context.Context, in *registryv1beta1.ListStorageProvidersRequest, opts ...grpc.CallOption)) *StorageRegistryAPIClient_ListStorageProviders_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]grpc.CallOption, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(grpc.CallOption)
}
}
run(args[0].(context.Context), args[1].(*registryv1beta1.ListStorageProvidersRequest), variadicArgs...)
})
return _c
}
func (_c *StorageRegistryAPIClient_ListStorageProviders_Call) Return(_a0 *registryv1beta1.ListStorageProvidersResponse, _a1 error) *StorageRegistryAPIClient_ListStorageProviders_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *StorageRegistryAPIClient_ListStorageProviders_Call) RunAndReturn(run func(context.Context, *registryv1beta1.ListStorageProvidersRequest, ...grpc.CallOption) (*registryv1beta1.ListStorageProvidersResponse, error)) *StorageRegistryAPIClient_ListStorageProviders_Call {
_c.Call.Return(run)
return _c
}
// NewStorageRegistryAPIClient creates a new instance of StorageRegistryAPIClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewStorageRegistryAPIClient(t interface {
mock.TestingT
Cleanup(func())
}) *StorageRegistryAPIClient {
mock := &StorageRegistryAPIClient{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}