19
19
package ocmd
20
20
21
21
import (
22
- "io"
22
+ "context"
23
+ "encoding/json"
24
+ "fmt"
23
25
"mime"
24
26
"net/http"
25
27
26
- "github.com/cs3org/reva/v2/internal/http/services/reqres"
28
+ gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
29
+ ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1"
30
+ rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
31
+ typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
27
32
"github.com/cs3org/reva/v2/pkg/appctx"
33
+ "github.com/cs3org/reva/v2/pkg/ocm/payload"
34
+ "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
35
+ "github.com/cs3org/reva/v2/pkg/utils"
36
+ "github.com/go-chi/render"
28
37
)
29
38
30
39
// var validate = validator.New()
31
40
32
41
type notifHandler struct {
42
+ gatewaySelector * pool.Selector [gateway.GatewayAPIClient ]
33
43
}
34
44
35
45
func (h * notifHandler ) init (c * config ) error {
46
+ gatewaySelector , err := pool .GatewaySelector (c .GatewaySvc )
47
+ if err != nil {
48
+ return err
49
+ }
50
+ h .gatewaySelector = gatewaySelector
51
+
36
52
return nil
37
53
}
38
54
@@ -42,25 +58,100 @@ func (h *notifHandler) init(c *config) error {
42
58
func (h * notifHandler ) Notifications (w http.ResponseWriter , r * http.Request ) {
43
59
ctx := r .Context ()
44
60
log := appctx .GetLogger (ctx )
45
- req , err := getNotification (r )
61
+ req , err := getNotification (w , r )
46
62
if err != nil {
47
- reqres . WriteError (w , r , reqres . APIErrorInvalidParameter , err .Error (), nil )
63
+ renderErrorBadRequest (w , r , http . StatusBadRequest , err .Error ())
48
64
return
49
65
}
50
66
51
67
// TODO(lopresti) this is all to be implemented. For now we just log what we got
52
68
log .Debug ().Msgf ("Received OCM notification: %+v" , req )
53
69
54
- // this is to please Nextcloud
55
- w .WriteHeader (http .StatusCreated )
70
+ var status * rpc.Status
71
+ switch req .NotificationType {
72
+ case payload .SHARE_UNSHARED :
73
+ if req .Notification .Grantee == "" {
74
+ renderErrorBadRequest (w , r , http .StatusBadRequest , "grantee is required" )
75
+ }
76
+ status , err = h .handleShareUnshared (ctx , req )
77
+ if err != nil {
78
+ log .Err (err ).Any ("NotificationRequest" , req ).Msg ("error getting gateway client" )
79
+ renderErrorBadRequest (w , r , http .StatusInternalServerError , status .GetMessage ())
80
+ }
81
+ case payload .SHARE_CHANGE_PERMISSION :
82
+ // TODO implement the SHARE_CHANGE_PERMISSION
83
+ w .WriteHeader (http .StatusNotImplemented )
84
+ return
85
+ default :
86
+ renderErrorBadRequest (w , r , http .StatusBadRequest , "NotificationType " + req .NotificationType + " is not supported" )
87
+ return
88
+ }
89
+ // parse the response status
90
+ switch status .GetCode () {
91
+ case rpc .Code_CODE_OK :
92
+ w .WriteHeader (http .StatusCreated )
93
+ return
94
+ case rpc .Code_CODE_INVALID_ARGUMENT :
95
+ renderErrorBadRequest (w , r , http .StatusBadRequest , status .GetMessage ())
96
+ return
97
+ case rpc .Code_CODE_UNAUTHENTICATED :
98
+ w .WriteHeader (http .StatusUnauthorized )
99
+ return
100
+ case rpc .Code_CODE_PERMISSION_DENIED :
101
+ w .WriteHeader (http .StatusForbidden )
102
+ return
103
+ default :
104
+ log .Error ().Str ("code" , status .GetCode ().String ()).Str ("message" , status .GetMessage ()).Str ("NotificationType" , req .NotificationType ).Msg ("error handling notification" )
105
+ w .WriteHeader (http .StatusInternalServerError )
106
+ }
107
+ }
108
+
109
+ func (h * notifHandler ) handleShareUnshared (ctx context.Context , req * payload.NotificationRequest ) (* rpc.Status , error ) {
110
+ gatewayClient , err := h .gatewaySelector .Next ()
111
+ if err != nil {
112
+ return nil , fmt .Errorf ("error getting gateway client: %w" , err )
113
+ }
114
+
115
+ o := & typesv1beta1.Opaque {}
116
+ utils .AppendPlainToOpaque (o , "grantee" , req .Notification .Grantee )
117
+
118
+ res , err := gatewayClient .DeleteOCMCoreShare (ctx , & ocmcore.DeleteOCMCoreShareRequest {
119
+ Id : req .ProviderId ,
120
+ Opaque : o ,
121
+ })
122
+ if err != nil {
123
+ return nil , fmt .Errorf ("error calling DeleteOCMCoreShare: %w" , err )
124
+ }
125
+ return res .GetStatus (), nil
56
126
}
57
127
58
- func getNotification (r * http.Request ) (string , error ) {
59
- // var req notificationRequest
128
+ func getNotification (w http.ResponseWriter , r * http.Request ) (* payload.NotificationRequest , error ) {
60
129
contentType , _ , err := mime .ParseMediaType (r .Header .Get ("Content-Type" ))
61
130
if err == nil && contentType == "application/json" {
62
- bytes , _ := io .ReadAll (r .Body )
63
- return string (bytes ), nil
131
+ n := & payload.NotificationRequest {}
132
+ err := json .NewDecoder (r .Body ).Decode (& n )
133
+ if err != nil {
134
+ return nil , err
135
+ }
136
+ return n , nil
137
+ }
138
+ return nil , err
139
+ }
140
+
141
+ func renderJSON (w http.ResponseWriter , r * http.Request , statusCode int , resp any ) {
142
+ render .Status (r , statusCode )
143
+ render .JSON (w , r , resp )
144
+ }
145
+
146
+ func renderErrorBadRequest (w http.ResponseWriter , r * http.Request , statusCode int , message string ) {
147
+ resp := & payload.ErrorMessageResponse {
148
+ Message : "BAD_REQUEST" ,
149
+ ValidationErrors : []* payload.ValidationError {
150
+ {
151
+ Name : "Notification" ,
152
+ Message : message ,
153
+ },
154
+ },
64
155
}
65
- return "" , nil
156
+ renderJSON ( w , r , http . StatusBadRequest , resp )
66
157
}
0 commit comments