@@ -44,6 +44,7 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
44
44
(Just ProcessedJSON {payKeys}, _) -> payKeys
45
45
(Just ProcessedUrlEncoded {payKeys}, _) -> payKeys
46
46
(Just RawJSON {}, Just cls) -> cls
47
+ (Just PgrstPatch {payFields}, _) -> payFields
47
48
_ -> S. empty
48
49
return (checkedPayload, cols)
49
50
where
@@ -69,6 +70,12 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
69
70
(MTTextPlain , True ) -> Right $ RawPay reqBody
70
71
(MTTextXML , True ) -> Right $ RawPay reqBody
71
72
(MTOctetStream , True ) -> Right $ RawPay reqBody
73
+ (MTVndPgrstPatch , False ) ->
74
+ if isJust columns
75
+ then Right $ RawJSON reqBody
76
+ -- Error message too generic?
77
+ else note " All objects should contain 3 key-vals: 'op','path' and 'value', where op and path must be a string"
78
+ (pgrstPatchPayloadFields reqBody =<< JSON. decode reqBody)
72
79
(ct, _) -> Left $ " Content-Type not acceptable: " <> MediaType. toMime ct
73
80
74
81
shouldParsePayload = case action of
@@ -78,10 +85,10 @@ getPayload reqBody contentMediaType QueryParams{qsColumns} action = do
78
85
_ -> False
79
86
80
87
columns = case action of
81
- ActDb (ActRelationMut _ MutationCreate ) -> qsColumns
82
- ActDb (ActRelationMut _ MutationUpdate ) -> qsColumns
83
- ActDb (ActRoutine _ Inv ) -> qsColumns
84
- _ -> Nothing
88
+ ActDb (ActRelationMut _ MutationCreate ) -> qsColumns
89
+ ActDb (ActRelationMut _ ( MutationUpdate _) ) -> qsColumns
90
+ ActDb (ActRoutine _ Inv ) -> qsColumns
91
+ _ -> Nothing
85
92
86
93
isProc = case action of
87
94
ActDb (ActRoutine _ _) -> True
@@ -136,3 +143,45 @@ payloadAttributes raw json =
136
143
_ -> Just emptyPJArray
137
144
where
138
145
emptyPJArray = ProcessedJSON (JSON. encode emptyArray) S. empty
146
+
147
+ -- Here, we verify the following about pgrst patch body:
148
+ -- 1. The JSON must be a json array.
149
+ -- 2. All objects in the array must have only these three fields:
150
+ -- 'op', 'path', 'value'.
151
+ -- 3. Finally, extract the 'path' values as fields
152
+ --
153
+ -- TODO: Return (Either ByteString Payload) for better error messages
154
+ pgrstPatchPayloadFields :: RequestBody -> JSON. Value -> Maybe Payload
155
+ pgrstPatchPayloadFields raw (JSON. Array arr) =
156
+ if V. all isValidPatchObject arr
157
+ then PgrstPatch raw . S. fromList <$> getPaths arr
158
+ else Nothing
159
+ where
160
+ isValidPatchObject (JSON. Object o) =
161
+ KM. member " op" o &&
162
+ KM. member " path" o &&
163
+ KM. member " value" o &&
164
+ length (KM. keys o) == 3
165
+ isValidPatchObject _ = False
166
+
167
+ getPaths :: V. Vector JSON. Value -> Maybe [Text ]
168
+ getPaths ar = if any isNothing maybePaths || not (all extractOp $ V. toList ar)
169
+ then Nothing
170
+ else Just $ catMaybes maybePaths
171
+ where
172
+ maybePaths :: [Maybe Text ]
173
+ maybePaths = map extractPath $ V. toList ar
174
+
175
+ extractOp (JSON. Object o) =
176
+ case KM. lookup " op" o of
177
+ Just op -> op == " set" -- we only have "set" operation, for now
178
+ Nothing -> False
179
+ extractOp _ = False
180
+
181
+ extractPath (JSON. Object o) =
182
+ case KM. lookup " path" o of
183
+ Just (JSON. String path) -> Just path
184
+ _ -> Nothing
185
+ extractPath _ = Nothing
186
+
187
+ pgrstPatchPayloadFields _ _ = Nothing
0 commit comments