github.com/cs3org/reva/v2@v2.27.7/pkg/publicshare/manager/owncloudsql/conversions.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package owncloudsql
    20  
    21  import (
    22  	"context"
    23  	"time"
    24  
    25  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    26  	rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
    27  	link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
    28  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    29  	typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
    30  	"github.com/cs3org/reva/v2/pkg/conversions"
    31  	"github.com/cs3org/reva/v2/pkg/rgrpc/status"
    32  	"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
    33  	"github.com/jellydator/ttlcache/v2"
    34  )
    35  
    36  // DBShare stores information about user and public shares.
    37  type DBShare struct {
    38  	ID           string
    39  	UIDOwner     string
    40  	UIDInitiator string
    41  	ItemStorage  string
    42  	FileSource   string
    43  	ItemType     string // 'file' or 'folder'
    44  	ShareWith    string
    45  	Token        string
    46  	Expiration   string
    47  	Permissions  int
    48  	ShareType    int
    49  	ShareName    string
    50  	STime        int
    51  	FileTarget   string
    52  	RejectedBy   string
    53  	State        int
    54  	Parent       int
    55  }
    56  
    57  // UserConverter describes an interface for converting user ids to names and back
    58  type UserConverter interface {
    59  	UserNameToUserID(ctx context.Context, username string) (*userpb.UserId, error)
    60  	UserIDToUserName(ctx context.Context, userid *userpb.UserId) (string, error)
    61  }
    62  
    63  // GatewayUserConverter converts usernames and ids using the gateway
    64  type GatewayUserConverter struct {
    65  	gwAddr string
    66  
    67  	IDCache   *ttlcache.Cache
    68  	NameCache *ttlcache.Cache
    69  }
    70  
    71  // NewGatewayUserConverter returns a instance of GatewayUserConverter
    72  func NewGatewayUserConverter(gwAddr string) *GatewayUserConverter {
    73  	IDCache := ttlcache.NewCache()
    74  	_ = IDCache.SetTTL(30 * time.Second)
    75  	IDCache.SkipTTLExtensionOnHit(true)
    76  	NameCache := ttlcache.NewCache()
    77  	_ = NameCache.SetTTL(30 * time.Second)
    78  	NameCache.SkipTTLExtensionOnHit(true)
    79  
    80  	return &GatewayUserConverter{
    81  		gwAddr:    gwAddr,
    82  		IDCache:   IDCache,
    83  		NameCache: NameCache,
    84  	}
    85  }
    86  
    87  // UserIDToUserName converts a user ID to an username
    88  func (c *GatewayUserConverter) UserIDToUserName(ctx context.Context, userid *userpb.UserId) (string, error) {
    89  	username, err := c.NameCache.Get(userid.String())
    90  	if err == nil {
    91  		return username.(string), nil
    92  	}
    93  
    94  	gwConn, err := pool.GetGatewayServiceClient(c.gwAddr)
    95  	if err != nil {
    96  		return "", err
    97  	}
    98  	getUserResponse, err := gwConn.GetUser(ctx, &userpb.GetUserRequest{
    99  		UserId:                 userid,
   100  		SkipFetchingUserGroups: true,
   101  	})
   102  	if err != nil {
   103  		return "", err
   104  	}
   105  	if getUserResponse.Status.Code != rpc.Code_CODE_OK {
   106  		return "", status.NewErrorFromCode(getUserResponse.Status.Code, "gateway")
   107  	}
   108  	_ = c.NameCache.Set(userid.String(), getUserResponse.User.Username)
   109  	return getUserResponse.User.Username, nil
   110  }
   111  
   112  // UserNameToUserID converts a username to an user ID
   113  func (c *GatewayUserConverter) UserNameToUserID(ctx context.Context, username string) (*userpb.UserId, error) {
   114  	id, err := c.IDCache.Get(username)
   115  	if err == nil {
   116  		return id.(*userpb.UserId), nil
   117  	}
   118  
   119  	gwConn, err := pool.GetGatewayServiceClient(c.gwAddr)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	getUserResponse, err := gwConn.GetUserByClaim(ctx, &userpb.GetUserByClaimRequest{
   124  		Claim:                  "username",
   125  		Value:                  username,
   126  		SkipFetchingUserGroups: true,
   127  	})
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	if getUserResponse.Status.Code != rpc.Code_CODE_OK {
   132  		return nil, status.NewErrorFromCode(getUserResponse.Status.Code, "gateway")
   133  	}
   134  	_ = c.IDCache.Set(username, getUserResponse.User.Id)
   135  	return getUserResponse.User.Id, nil
   136  }
   137  
   138  func resourceTypeToItem(r provider.ResourceType) string {
   139  	switch r {
   140  	case provider.ResourceType_RESOURCE_TYPE_FILE:
   141  		return "file"
   142  	case provider.ResourceType_RESOURCE_TYPE_CONTAINER:
   143  		return "folder"
   144  	case provider.ResourceType_RESOURCE_TYPE_REFERENCE:
   145  		return "reference"
   146  	case provider.ResourceType_RESOURCE_TYPE_SYMLINK:
   147  		return "symlink"
   148  	default:
   149  		return ""
   150  	}
   151  }
   152  
   153  func sharePermToInt(p *provider.ResourcePermissions) int {
   154  	return int(conversions.RoleFromResourcePermissions(p, true).OCSPermissions())
   155  }
   156  
   157  func intTosharePerm(p int) (*provider.ResourcePermissions, error) {
   158  	perms, err := conversions.NewPermissions(p)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	return conversions.RoleFromOCSPermissions(perms, nil).CS3ResourcePermissions(), nil
   164  }
   165  
   166  func formatUserID(u *userpb.UserId) string {
   167  	return u.OpaqueId
   168  }
   169  
   170  // ConvertToCS3PublicShare converts a DBShare to a CS3API public share
   171  func (m *mgr) ConvertToCS3PublicShare(ctx context.Context, s DBShare) (*link.PublicShare, error) {
   172  	ts := &typespb.Timestamp{
   173  		Seconds: uint64(s.STime),
   174  	}
   175  	permissions, err := intTosharePerm(s.Permissions)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  	owner, err := m.userConverter.UserNameToUserID(ctx, s.UIDOwner)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  	var creator *userpb.UserId
   184  	if s.UIDOwner == s.UIDInitiator {
   185  		creator = owner
   186  	} else {
   187  		creator, err = m.userConverter.UserNameToUserID(ctx, s.UIDOwner)
   188  		if err != nil {
   189  			return nil, err
   190  		}
   191  	}
   192  	pwd := false
   193  	if s.ShareWith != "" {
   194  		pwd = true
   195  	}
   196  	var expires *typespb.Timestamp
   197  	if s.Expiration != "" {
   198  		t, err := time.Parse("2006-01-02 15:04:05", s.Expiration)
   199  		if err != nil {
   200  			t, err = time.Parse("2006-01-02 15:04:05-07:00", s.Expiration)
   201  		}
   202  		if err == nil {
   203  			expires = &typespb.Timestamp{
   204  				Seconds: uint64(t.Unix()),
   205  			}
   206  		}
   207  	}
   208  	return &link.PublicShare{
   209  		Id: &link.PublicShareId{
   210  			OpaqueId: s.ID,
   211  		},
   212  		ResourceId: &provider.ResourceId{
   213  			SpaceId:  s.ItemStorage,
   214  			OpaqueId: s.FileSource,
   215  		},
   216  		Permissions:       &link.PublicSharePermissions{Permissions: permissions},
   217  		Owner:             owner,
   218  		Creator:           creator,
   219  		Token:             s.Token,
   220  		DisplayName:       s.ShareName,
   221  		PasswordProtected: pwd,
   222  		Expiration:        expires,
   223  		Ctime:             ts,
   224  		Mtime:             ts,
   225  	}, nil
   226  }