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 }