From 2d1ef54533b4e52010467966bcbe536fada8d62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Franke?= Date: Fri, 7 Jun 2024 12:54:56 +0200 Subject: [PATCH] Add last types --- dsp/contract_types.go | 2 +- dsp/transfer_types.go | 99 ++++++++++++++++++++++++++++ dsp/validators.go | 58 ++++++++++++++++ go.mod | 11 +++- go.sum | 18 +++++ odrl/types.go | 12 ++-- odrl/validators.go | 149 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 341 insertions(+), 8 deletions(-) create mode 100644 dsp/transfer_types.go create mode 100644 dsp/validators.go create mode 100644 odrl/validators.go diff --git a/dsp/contract_types.go b/dsp/contract_types.go index beb3ed0..2342ac2 100644 --- a/dsp/contract_types.go +++ b/dsp/contract_types.go @@ -82,7 +82,7 @@ type ContractNegotiation struct { Type string `json:"@type" validate:"required,eq=dspace:ContractNegotiation"` ProviderPID string `json:"dspace:providerPid" validate:"required"` ConsumerPID string `json:"dspace:consumerPid" validate:"required"` - State string `json:"dspace:state" validate:"required"` // TODO: Implement custom verifier + State string `json:"dspace:state" validate:"required,contract_state"` } // ContractNegotiationError is a response to show the state of the contract negotiation. diff --git a/dsp/transfer_types.go b/dsp/transfer_types.go new file mode 100644 index 0000000..e8e69e0 --- /dev/null +++ b/dsp/transfer_types.go @@ -0,0 +1,99 @@ +// Copyright 2024 go-dataspace +// +// 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 +// +// https://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. + +package dsp + +import "github.com/go-dataspace/run-dsp/jsonld" + +// TransferRequestMessage requests a data transfer. +type TransferRequestMessage struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferRequestMessage"` + AgreementID string `json:"dspace:agreementID" validate:"required"` + Format string `json:"dct:format" validate:"required"` + DataAddress DataAddress `json:"dspace:dataAddress"` + CallbackAddress string `json:"dspace:callbackAddress" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid" validate:"required"` +} + +// TransferStartMessage signals a transfer start. +type TransferStartMessage struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferStartMessage"` + ProviderPID string `json:"dspace:providerPid" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid" validate:"required"` + DataAddress DataAddress `json:"dspace:dataAddress"` +} + +// TransferSuspensionMessage signals the suspension of a datatransfer. +type TransferSuspensionMessage struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferSuspensionMessage"` + ProviderPID string `json:"dspace:providerPid,omitempty" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid,omitempty" validate:"required"` + Code string `json:"code,omitempty"` + Reason []map[string]any `json:"reason,omitempty"` +} + +// TransferCompletionMessage signals the completion of a datatransfer. +type TransferCompletionMessage struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferCompletionMessage"` + ProviderPID string `json:"dspace:providerPid,omitempty" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid,omitempty" validate:"required"` +} + +// TransferTerminationMessage signals the suspension of a datatransfer. +type TransferTerminationMessage struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferTerminationMessage"` + ProviderPID string `json:"dspace:providerPid,omitempty" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid,omitempty" validate:"required"` + Code string `json:"code,omitempty"` + Reason []map[string]any `json:"reason,omitempty"` +} + +// TransferProcess are state change reponses. +type TransferProcess struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferProcess"` + ProviderPID string `json:"dspace:providerPid,omitempty" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid,omitempty" validate:"required"` + State string `json:"dspace:state" validate:"required,transfer_state"` +} + +// TransferError signals the suspension of a datatransfer. +type TransferError struct { + Context jsonld.Context `json:"@context,omitempty"` + Type string `json:"@type,omitempty" validate:"required,eq=dspace:TransferError"` + ProviderPID string `json:"dspace:providerPid,omitempty" validate:"required"` + ConsumerPID string `json:"dspace:consumerPid,omitempty" validate:"required"` + Code string `json:"code,omitempty"` + Reason []map[string]any `json:"reason,omitempty"` +} + +// DataAddress represents a dataspace data address. +type DataAddress struct { + Type string `json:"@type,omitempty" validate:"required,eq=dspace:DataAddress"` + EndpointType string `json:"endpointType" validate:"required"` + Endpoint string `json:"endpoint" validate:"required"` + EndpointProperties []EndpointProperty `json:"endpointProperties"` +} + +// EndpointProperty represents endpoint properties. +type EndpointProperty struct { + Type string `json:"@type,omitempty" validate:"required,eq=dspace:EndpointProperty"` + Name string `json:"dspace:name" validate:"required"` + Value string `json:"dspace:value" validate:"required"` +} diff --git a/dsp/validators.go b/dsp/validators.go new file mode 100644 index 0000000..ffb567f --- /dev/null +++ b/dsp/validators.go @@ -0,0 +1,58 @@ +// Copyright 2024 go-dataspace +// +// 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 +// +// https://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. + +package dsp + +import ( + "slices" + + "github.com/go-dataspace/run-dsp/odrl" + "github.com/go-playground/validator/v10" +) + +func transferProcessState(fl validator.FieldLevel) bool { + states := []string{ + "dspace:REQUESTED", + "dspace:STARTED", + "dspace:TERMINATED", + "dspace:COMPLETED", + "dspace:SUSPENDED", + } + return slices.Contains(states, fl.Field().String()) +} + +func contractNegotiationState(fl validator.FieldLevel) bool { + states := []string{ + "dspace:REQUESTED", + "dspace:OFFERED", + "dspace:ACCEPTED", + "dspace:AGREED", + "dspace:VERIFIED", + "dspace:FINALIZED", + "dspace:TERMINATED", + } + return slices.Contains(states, fl.Field().String()) +} + +// This registers all the validators of this package, and also calls the odrl register function +// as this package uses the odrl structs as well. +func RegisterValidators(v *validator.Validate) error { + if err := v.RegisterValidation("transfer_state", transferProcessState); err != nil { + return err + } + if err := v.RegisterValidation("contract_state", contractNegotiationState); err != nil { + return err + } + return odrl.RegisterValidators(v) +} diff --git a/go.mod b/go.mod index 4b6845e..38219ee 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,20 @@ module github.com/go-dataspace/run-dsp -go 1.22.3 +go 1.22 require ( github.com/alecthomas/kong v0.9.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.21.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/samber/slog-http v1.3.1 // indirect go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index a830c40..ab4e9a7 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,28 @@ github.com/alecthomas/kong v0.9.0 h1:G5diXxc85KvoV2f0ZRVuMsi45IrBgx9zDNGNj165aPA= github.com/alecthomas/kong v0.9.0/go.mod h1:Y47y5gKfHp1hDc7CH7OeXgLIpp+Q2m1Ni0L5s3bI8Os= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.21.0 h1:4fZA11ovvtkdgaeev9RGWPgc1uj3H8W+rNYyH/ySBb0= +github.com/go-playground/validator/v10 v10.21.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/samber/slog-http v1.3.1 h1:Fho8CGX4elTKAXFKCNGloRAz2yWt1WD+vXpO9iylQ9g= github.com/samber/slog-http v1.3.1/go.mod h1:n6h4x2ZBeTgLqMKf95EuNlU6mcJF1b/RVLxo1od5+V0= go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/odrl/types.go b/odrl/types.go index 14a753d..21701c4 100644 --- a/odrl/types.go +++ b/odrl/types.go @@ -55,7 +55,7 @@ type Reference struct { // Permission is a permisson entry. type Permission struct { AbstractPolicyRule - Action string `json:"action" validate:"required"` // TODO custom verifier. + Action string `json:"action" validate:"required,odrl_action"` Constraint []Constraint `json:"constraint,omitempty" validate:"gte=1,dive"` Duty Duty `json:"duty,omitempty" validate:"dive"` } @@ -64,16 +64,16 @@ type Permission struct { type Duty struct { AbstractPolicyRule ID string `json:"@id"` - Action string `json:"action" validate:"required"` // TODO: custom verifier. + Action string `json:"action" validate:"required,odrl_action"` Constraint []Constraint `json:"constraint,omitempty" validate:"gte=1,dive"` } // Constraint is an ODRL constraint. type Constraint struct { - RightOperand string `json:"odrl:rightOperand"` // TODO: implement custom verifier - RightOperandReference Reference `json:"odrl:rightOperandReference"` - LeftOperand string `json:"odrl:leftOperand"` // TODO: implement custom verifier. - Operator string `json:"odrl:operator"` // TODO: implment custom verifier. + RightOperand map[string]any `json:"odrl:rightOperand"` + RightOperandReference Reference `json:"odrl:rightOperandReference"` + LeftOperand string `json:"odrl:leftOperand" validate:"odrl_leftoperand"` + Operator string `json:"odrl:operator" validate:"odrl_operator"` // TODO: implment custom verifier. } // Agreement is an ODRL agreement. diff --git a/odrl/validators.go b/odrl/validators.go new file mode 100644 index 0000000..f532f7d --- /dev/null +++ b/odrl/validators.go @@ -0,0 +1,149 @@ +// Copyright 2024 go-dataspace +// +// 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 +// +// https://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. + +package odrl + +import ( + "slices" + + "github.com/go-playground/validator/v10" +) + +func action(fl validator.FieldLevel) bool { + states := []string{ + "odrl:delete", + "odrl:execute", + "cc:SourceCode", + "odrl:anonymize", + "odrl:extract", + "odrl:read", + "odrl:index", + "odrl:compensate", + "odrl:sell", + "odrl:derive", + "odrl:ensureExclusivity", + "odrl:annotate", + "cc:Reproduction", + "odrl:translate", + "odrl:include", + "cc:DerivativeWorks", + "cc:Distribution", + "odrl:textToSpeech", + "odrl:inform", + "odrl:grantUse", + "odrl:archive", + "odrl:modify", + "odrl:aggregate", + "odrl:attribute", + "odrl:nextPolicy", + "odrl:digitize", + "cc:Attribution", + "odrl:install", + "odrl:concurrentUse", + "odrl:distribute", + "odrl:synchronize", + "odrl:move", + "odrl:obtainConsent", + "odrl:print", + "cc:Notice", + "odrl:give", + "odrl:uninstall", + "cc:Sharing", + "odrl:reviewPolicy", + "odrl:watermark", + "odrl:play", + "odrl:reproduce", + "odrl:transform", + "odrl:display", + "odrl:stream", + "cc:ShareAlike", + "odrl:acceptTracking", + "cc:CommericalUse", + "odrl:present", + "odrl:use", + } + return slices.Contains(states, fl.Field().String()) +} + +func leftOperand(fl validator.FieldLevel) bool { + states := []string{ + "odrl:absolutePosition", + "odrl:absoluteSize", + "odrl:absoluteSpatialPosition", + "odrl:absoluteTemporalPosition", + "odrl:count", + "odrl:dateTime", + "odrl:delayPeriod", + "odrl:deliveryChannel", + "odrl:device", + "odrl:elapsedTime", + "odrl:event", + "odrl:fileFormat", + "odrl:industry", + "odrl:language", + "odrl:media", + "odrl:meteredTime", + "odrl:payAmount", + "odrl:percentage", + "odrl:product", + "odrl:purpose", + "odrl:recipient", + "odrl:relativePosition", + "odrl:relativeSize", + "odrl:relativeSpatialPosition", + "odrl:relativeTemporalPosition", + "odrl:resolution", + "odrl:spatial", + "odrl:spatialCoordinates", + "odrl:system", + "odrl:systemDevice", + "odrl:timeInterval", + "odrl:unitOfCount", + "odrl:version", + "odrl:virtualLocation", + } + return slices.Contains(states, fl.Field().String()) +} + +func operator(fl validator.FieldLevel) bool { + states := []string{ + "odrl:eq", + "odrl:gt", + "odrl:gteq", + "odrl:hasPart", + "odrl:isA", + "odrl:isAllOf", + "odrl:isAnyOf", + "odrl:isNoneOf", + "odrl:isPartOf", + "odrl:lt", + "odrl:term-lteq", + "odrl:neq", + } + return slices.Contains(states, fl.Field().String()) +} + +// This registers all the validators of this package. +func RegisterValidators(v *validator.Validate) error { + if err := v.RegisterValidation("odrl_action", action); err != nil { + return err + } + if err := v.RegisterValidation("odrl_leftoperand", leftOperand); err != nil { + return err + } + if err := v.RegisterValidation("odrl_operator", operator); err != nil { + return err + } + return nil +}