github.com/cs3org/reva/v2@v2.27.7/internal/http/services/ocmd/protocols.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 ocmd 20 21 import ( 22 "encoding/json" 23 "errors" 24 "fmt" 25 "reflect" 26 "strings" 27 28 ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" 29 providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 30 ocmshare "github.com/cs3org/reva/v2/pkg/ocm/share" 31 utils "github.com/cs3org/reva/v2/pkg/utils" 32 ) 33 34 // Protocols is the list of protocols. 35 type Protocols []Protocol 36 37 // Protocol represents the way of access the resource 38 // in the OCM share. 39 type Protocol interface { 40 // ToOCMProtocol convert the protocol to a ocm Protocol struct 41 ToOCMProtocol() *ocm.Protocol 42 } 43 44 // protocols supported by the OCM API 45 46 // WebDAV contains the parameters for the WebDAV protocol. 47 type WebDAV struct { 48 SharedSecret string `json:"sharedSecret" validate:"required"` 49 Permissions []string `json:"permissions" validate:"required,dive,required,oneof=read write share"` 50 URL string `json:"url" validate:"required"` 51 } 52 53 // ToOCMProtocol convert the protocol to a ocm Protocol struct. 54 func (w *WebDAV) ToOCMProtocol() *ocm.Protocol { 55 perms := &ocm.SharePermissions{ 56 Permissions: &providerv1beta1.ResourcePermissions{}, 57 } 58 for _, p := range w.Permissions { 59 switch p { 60 case "read": 61 perms.Permissions.GetPath = true 62 perms.Permissions.GetQuota = true 63 perms.Permissions.InitiateFileDownload = true 64 perms.Permissions.ListContainer = true 65 perms.Permissions.ListRecycle = true 66 perms.Permissions.Stat = true 67 case "write": 68 perms.Permissions.InitiateFileUpload = true 69 perms.Permissions.RestoreRecycleItem = true 70 perms.Permissions.CreateContainer = true 71 perms.Permissions.Delete = true 72 perms.Permissions.Move = true 73 } 74 } 75 76 return ocmshare.NewWebDAVProtocol(w.URL, w.SharedSecret, perms) 77 } 78 79 // Webapp contains the parameters for the Webapp protocol. 80 type Webapp struct { 81 URITemplate string `json:"uriTemplate" validate:"required"` 82 ViewMode string `json:"viewMode" validate:"required,dive,required,oneof=view read write"` 83 } 84 85 // ToOCMProtocol convert the protocol to a ocm Protocol struct. 86 func (w *Webapp) ToOCMProtocol() *ocm.Protocol { 87 return ocmshare.NewWebappProtocol(w.URITemplate, utils.GetAppViewMode(w.ViewMode)) 88 } 89 90 // Datatx contains the parameters for the Datatx protocol. 91 type Datatx struct { 92 SharedSecret string `json:"sharedSecret" validate:"required"` 93 SourceURI string `json:"srcUri" validate:"required"` 94 Size uint64 `json:"size" validate:"required"` 95 } 96 97 // ToOCMProtocol convert the protocol to a ocm Protocol struct. 98 func (w *Datatx) ToOCMProtocol() *ocm.Protocol { 99 return ocmshare.NewTransferProtocol(w.SourceURI, w.SharedSecret, w.Size) 100 } 101 102 var protocolImpl = map[string]reflect.Type{ 103 "webdav": reflect.TypeOf(WebDAV{}), 104 "webapp": reflect.TypeOf(Webapp{}), 105 "datatx": reflect.TypeOf(Datatx{}), 106 } 107 108 // UnmarshalJSON implements the Unmarshaler interface. 109 func (p *Protocols) UnmarshalJSON(data []byte) error { 110 var prot map[string]json.RawMessage 111 if err := json.Unmarshal(data, &prot); err != nil { 112 return err 113 } 114 115 *p = []Protocol{} 116 117 for name, d := range prot { 118 var res Protocol 119 120 // we do not support the OCM v1.0 properties for now, therefore just skip or bail out 121 if name == "name" { 122 continue 123 } 124 if name == "options" { 125 var opt map[string]any 126 if err := json.Unmarshal(d, &opt); err != nil || len(opt) > 0 { 127 return fmt.Errorf("protocol options not supported: %s", string(d)) 128 } 129 continue 130 } 131 ctype, ok := protocolImpl[name] 132 if !ok { 133 return fmt.Errorf("protocol %s not recognised", name) 134 } 135 res = reflect.New(ctype).Interface().(Protocol) 136 if err := json.Unmarshal(d, &res); err != nil { 137 return err 138 } 139 140 *p = append(*p, res) 141 } 142 return nil 143 } 144 145 // MarshalJSON implements the Marshaler interface. 146 func (p Protocols) MarshalJSON() ([]byte, error) { 147 if len(p) == 0 { 148 return nil, errors.New("no protocol defined") 149 } 150 d := make(map[string]any) 151 for _, prot := range p { 152 d[getProtocolName(prot)] = prot 153 } 154 // fill in the OCM v1.0 properties 155 d["name"] = "multi" 156 d["options"] = map[string]any{} 157 return json.Marshal(d) 158 } 159 160 func getProtocolName(p Protocol) string { 161 n := reflect.TypeOf(p).String() 162 s := strings.Split(n, ".") 163 return strings.ToLower(s[len(s)-1]) 164 }