github.com/cs3org/reva/v2@v2.27.7/pkg/cbox/utils/conversions.go (about)

     1  // Copyright 2018-2023 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package utils
    20  
    21  import (
    22  	"context"
    23  	"errors"
    24  	"time"
    25  
    26  	gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
    27  	grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
    28  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    29  	rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
    30  	collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
    31  	link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
    32  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    33  	typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
    34  	"github.com/cs3org/reva/v2/pkg/conversions"
    35  )
    36  
    37  // DBShare stores information about user and public shares.
    38  type DBShare struct {
    39  	ID                           string
    40  	UIDOwner                     string
    41  	UIDInitiator                 string
    42  	Prefix                       string
    43  	ItemSource                   string
    44  	ItemType                     string
    45  	ShareWith                    string
    46  	Token                        string
    47  	Expiration                   string
    48  	Permissions                  int
    49  	ShareType                    int
    50  	ShareName                    string
    51  	STime                        int
    52  	FileTarget                   string
    53  	State                        int
    54  	Quicklink                    bool
    55  	Description                  string
    56  	NotifyUploads                bool
    57  	NotifyUploadsExtraRecipients string
    58  }
    59  
    60  // FormatGrantee formats a CS3API grantee to a string.
    61  func FormatGrantee(g *provider.Grantee) (int, string) {
    62  	var granteeType int
    63  	var formattedID string
    64  	switch g.Type {
    65  	case provider.GranteeType_GRANTEE_TYPE_USER:
    66  		granteeType = 0
    67  		formattedID = FormatUserID(g.GetUserId())
    68  	case provider.GranteeType_GRANTEE_TYPE_GROUP:
    69  		granteeType = 1
    70  		formattedID = FormatGroupID(g.GetGroupId())
    71  	default:
    72  		granteeType = -1
    73  	}
    74  	return granteeType, formattedID
    75  }
    76  
    77  // ExtractGrantee retrieves the CS3API grantee from a formatted string.
    78  func ExtractGrantee(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, t int, g string) (*provider.Grantee, error) {
    79  	var grantee provider.Grantee
    80  	switch t {
    81  	case 0:
    82  		grantee.Type = provider.GranteeType_GRANTEE_TYPE_USER
    83  		user, err := ExtractUserID(ctx, gateway, g)
    84  		if err != nil {
    85  			return nil, err
    86  		}
    87  		grantee.Id = &provider.Grantee_UserId{UserId: user}
    88  	case 1:
    89  		grantee.Type = provider.GranteeType_GRANTEE_TYPE_GROUP
    90  		group, err := ExtractGroupID(ctx, gateway, g)
    91  		if err != nil {
    92  			return nil, err
    93  		}
    94  		grantee.Id = &provider.Grantee_GroupId{GroupId: group}
    95  	default:
    96  		grantee.Type = provider.GranteeType_GRANTEE_TYPE_INVALID
    97  	}
    98  	return &grantee, nil
    99  }
   100  
   101  // ResourceTypeToItem maps a resource type to a string.
   102  func ResourceTypeToItem(r provider.ResourceType) string {
   103  	switch r {
   104  	case provider.ResourceType_RESOURCE_TYPE_FILE:
   105  		return "file"
   106  	case provider.ResourceType_RESOURCE_TYPE_CONTAINER:
   107  		return "folder"
   108  	case provider.ResourceType_RESOURCE_TYPE_REFERENCE:
   109  		return "reference"
   110  	case provider.ResourceType_RESOURCE_TYPE_SYMLINK:
   111  		return "symlink"
   112  	default:
   113  		return ""
   114  	}
   115  }
   116  
   117  // ResourceTypeToItemInt maps a resource type to an integer.
   118  func ResourceTypeToItemInt(r provider.ResourceType) int {
   119  	switch r {
   120  	case provider.ResourceType_RESOURCE_TYPE_CONTAINER:
   121  		return 0
   122  	case provider.ResourceType_RESOURCE_TYPE_FILE:
   123  		return 1
   124  	default:
   125  		return -1
   126  	}
   127  }
   128  
   129  // SharePermToInt maps read/write permissions to an integer.
   130  func SharePermToInt(p *provider.ResourcePermissions) int {
   131  	var perm int
   132  	switch {
   133  	case p.InitiateFileUpload && !p.InitiateFileDownload:
   134  		perm = 4
   135  	case p.InitiateFileUpload:
   136  		perm = 15
   137  	case p.InitiateFileDownload:
   138  		perm = 1
   139  	}
   140  	// TODO map denials and resharing; currently, denials are mapped to 0
   141  	return perm
   142  }
   143  
   144  // IntTosharePerm retrieves read/write permissions from an integer.
   145  func IntTosharePerm(p int, itemType string) *provider.ResourcePermissions {
   146  	switch p {
   147  	case 1:
   148  		return conversions.NewViewerRole().CS3ResourcePermissions()
   149  	case 15:
   150  		if itemType == "folder" {
   151  			return conversions.NewEditorRole().CS3ResourcePermissions()
   152  		}
   153  		return conversions.NewFileEditorRole().CS3ResourcePermissions()
   154  	case 4:
   155  		return conversions.NewUploaderRole().CS3ResourcePermissions()
   156  	default:
   157  		// TODO we may have other options, for now this is a denial
   158  		return &provider.ResourcePermissions{}
   159  	}
   160  }
   161  
   162  // IntToShareState retrieves the received share state from an integer.
   163  func IntToShareState(g int) collaboration.ShareState {
   164  	switch g {
   165  	case 0:
   166  		return collaboration.ShareState_SHARE_STATE_PENDING
   167  	case 1:
   168  		return collaboration.ShareState_SHARE_STATE_ACCEPTED
   169  	case -1:
   170  		return collaboration.ShareState_SHARE_STATE_REJECTED
   171  	default:
   172  		return collaboration.ShareState_SHARE_STATE_INVALID
   173  	}
   174  }
   175  
   176  // FormatUserID formats a CS3API user ID to a string.
   177  func FormatUserID(u *userpb.UserId) string {
   178  	return u.OpaqueId
   179  }
   180  
   181  // ExtractUserID retrieves a CS3API user ID from a string.
   182  func ExtractUserID(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, u string) (*userpb.UserId, error) {
   183  	userRes, err := gateway.GetUser(ctx, &userpb.GetUserRequest{
   184  		UserId: &userpb.UserId{OpaqueId: u},
   185  	})
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	if userRes.Status.Code != rpcv1beta1.Code_CODE_OK {
   190  		return nil, errors.New(userRes.Status.Message)
   191  	}
   192  
   193  	return userRes.User.Id, nil
   194  }
   195  
   196  // FormatGroupID formats a CS3API group ID to a string.
   197  func FormatGroupID(u *grouppb.GroupId) string {
   198  	return u.OpaqueId
   199  }
   200  
   201  // ExtractGroupID retrieves a CS3API group ID from a string.
   202  func ExtractGroupID(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, u string) (*grouppb.GroupId, error) {
   203  	groupRes, err := gateway.GetGroup(ctx, &grouppb.GetGroupRequest{
   204  		GroupId: &grouppb.GroupId{OpaqueId: u},
   205  	})
   206  	if err != nil {
   207  		return nil, err
   208  	}
   209  	if groupRes.Status.Code != rpcv1beta1.Code_CODE_OK {
   210  		return nil, errors.New(groupRes.Status.Message)
   211  	}
   212  	return groupRes.Group.Id, nil
   213  }
   214  
   215  // ConvertToCS3Share converts a DBShare to a CS3API collaboration share.
   216  func ConvertToCS3Share(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, s DBShare) (*collaboration.Share, error) {
   217  	ts := &typespb.Timestamp{
   218  		Seconds: uint64(s.STime),
   219  	}
   220  	owner, err := ExtractUserID(ctx, gateway, s.UIDOwner)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	creator, err := ExtractUserID(ctx, gateway, s.UIDInitiator)
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	grantee, err := ExtractGrantee(ctx, gateway, s.ShareType, s.ShareWith)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  
   233  	return &collaboration.Share{
   234  		Id: &collaboration.ShareId{
   235  			OpaqueId: s.ID,
   236  		},
   237  		//ResourceId:  &provider.Reference{StorageId: s.Prefix, NodeId: s.ItemSource},
   238  		ResourceId: &provider.ResourceId{
   239  			StorageId: s.Prefix,
   240  			OpaqueId:  s.ItemSource,
   241  		},
   242  		Permissions: &collaboration.SharePermissions{Permissions: IntTosharePerm(s.Permissions, s.ItemType)},
   243  		Grantee:     grantee,
   244  		Owner:       owner,
   245  		Creator:     creator,
   246  		Ctime:       ts,
   247  		Mtime:       ts,
   248  	}, nil
   249  }
   250  
   251  // ConvertToCS3ReceivedShare converts a DBShare to a CS3API collaboration received share.
   252  func ConvertToCS3ReceivedShare(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, s DBShare) (*collaboration.ReceivedShare, error) {
   253  	share, err := ConvertToCS3Share(ctx, gateway, s)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	return &collaboration.ReceivedShare{
   258  		Share: share,
   259  		State: IntToShareState(s.State),
   260  	}, nil
   261  }
   262  
   263  // ConvertToCS3PublicShare converts a DBShare to a CS3API public share.
   264  func ConvertToCS3PublicShare(ctx context.Context, gateway gatewayv1beta1.GatewayAPIClient, s DBShare) (*link.PublicShare, error) {
   265  	ts := &typespb.Timestamp{
   266  		Seconds: uint64(s.STime),
   267  	}
   268  	pwd := false
   269  	if s.ShareWith != "" {
   270  		pwd = true
   271  	}
   272  	var expires *typespb.Timestamp
   273  	if s.Expiration != "" {
   274  		t, err := time.Parse("2006-01-02 15:04:05", s.Expiration)
   275  		if err == nil {
   276  			expires = &typespb.Timestamp{
   277  				Seconds: uint64(t.Unix()),
   278  			}
   279  		}
   280  	}
   281  	owner, err := ExtractUserID(ctx, gateway, s.UIDOwner)
   282  	if err != nil {
   283  		return nil, err
   284  	}
   285  	creator, err := ExtractUserID(ctx, gateway, s.UIDInitiator)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  	return &link.PublicShare{
   290  		Id: &link.PublicShareId{
   291  			OpaqueId: s.ID,
   292  		},
   293  		ResourceId: &provider.ResourceId{
   294  			StorageId: s.Prefix,
   295  			OpaqueId:  s.ItemSource,
   296  		},
   297  		Permissions:                  &link.PublicSharePermissions{Permissions: IntTosharePerm(s.Permissions, s.ItemType)},
   298  		Owner:                        owner,
   299  		Creator:                      creator,
   300  		Token:                        s.Token,
   301  		DisplayName:                  s.ShareName,
   302  		PasswordProtected:            pwd,
   303  		Expiration:                   expires,
   304  		Ctime:                        ts,
   305  		Mtime:                        ts,
   306  		Quicklink:                    s.Quicklink,
   307  		Description:                  s.Description,
   308  		NotifyUploads:                s.NotifyUploads,
   309  		NotifyUploadsExtraRecipients: s.NotifyUploadsExtraRecipients,
   310  	}, nil
   311  }