ActionService.md 13.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
## Action Service

## Table of Contents <a name="TOC"></a>

- [Introduction](#introduction)
- [Action APIs](#action-apis)
    * [Registering an Action](#register-action)
    * [Get an Action by ID](#get-action)
    * [Retrieve Actions](#retrieve-action)
    * [Delete an Action by ID](#delete-action)
    * [Validate action](#regex-test)
12
    * [Version info endpoint](#version-info-endpoint)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
- [Current Limitations](#limitation)

## Introduction <a name="introduction"></a>
The high level design of this service can conceptually be thought of similar to the 'command' design pattern. Essentially this pattern decouples a trigger from an action. This is often used in UIs where a trigger is perhaps a user clicking a button and the action is a program function that is triggered by the click. There is often an optional context which can provide the action with data to use in the function, as well as to enable / disable the action for the user (perhaps if the data is not relevant to the action in question).

This service will allow an application to register an action (the function to be triggered). It will expect data (context) to come from OSDU to enable the action, and the application can register a filter (enable/disable) to say what data can be used with this action.

[Back to Table of Contents](#TOC)

## Action APIs <a name="action-apis"></a>
### Registering an Action <a name="register-action"></a>
This API allows registering an action in the form of a GET HTTPS URL and a filter. The filter specifies what data the action can be applied to.

> It is recommended that Admins first use the [Validate action](#regex-test) API, to make sure the action is acceptable and the output of the action with a test payload is as expected.

```
POST /api/register/v1/action
```
<details><summary>curl</summary>

```
curl --request POST \
  --url 'https://register-svc.osdu.com/api/register/v1/action' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common' \
  --data '{
        "id": "petrel-launch-project",
        "name": "Petrel Project",
        "description": "This action launches the Petrel projects landing page that holds the selected data.",
        "url": "https://myapp.osdu.com/action/{id}/{data.project}",
        "img": "https://mycdn.com/img.png",
        "contactEmail": "abc@test.com",
        "filter": {
            "entityType": ["regularheightfield", "project"],
            "source": ["petrel"],
            "version": ["*"]
         }
}'
```
</details>

The filter specifies what data the action can be applied to. Each property in the filter is either values representing an exact match for the data it can handle or a single wildcard '*' indicating that any data can match that property filter.

The URL given on the registration must be a fully qualified HTTPS GET request. The URL can support templates as shown above e.g. {data.project}, as well as regular expressions. These templates can be applied anywhere in the given URL (domain, path, query etc.)   The template values can be any property that matches a Record's payload. 

The filter specifies which Records your action can be used with. The retrieve API applies the template onto a given Record to create the fully qualified URL. For instance, the above URL could be applied to the following Record in Storage.
```
{
    "id": "common:doc:123456789",
    "kind": "common:petrel:regularheightfield:1.0.0",
    ...
    "data": {
        "project":"myPetrelProj"
    }
    ...
}
```

Because the filter of the action matches the Record (petrel and regularheightfield match the 'kind' and the version is a wildcard so matches 1.0.0), the resulting action after the template is applied would then be
```
https://myapp.osdu.com/action/common:doc:123456789/myPetrelProj
```

[Back to Table of Contents](#TOC)

## Get an Action by ID <a name="get-action"></a>
This API allows getting an action with a given Id.
```
GET /api/register/v1/action/{id}
```
<details><summary>curl</summary>

```
curl --request GET \
  --url 'https://register-svc.osdu.com/api/register/v1/action/petrel-launch-project' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common' 
```
</details>

[Back to Table of Contents](#TOC)

## Retrieve Actions <a name="retrieve-action"></a>
This API allows retrieving all actions that match a given filter. 
```
POST /api/register/v1/action:retrieve
```
So imagine you have a Record retrieved from OSDU:
```
{
   "id": "common:regularheightfield:123456",
   "kind": "common:petrel:regularheightfield:1.0.0",
   "acl": {
     "viewers": ["data.default.viewers@common.osdu.com"],
     "owners": ["data.default.owners@common.osdu.com"]
   },
   "legal": {
     "legaltags": ["common-sample-legaltag"],
     "otherRelevantDataCountries": ["FR","US","CA"]
   },
   "data": {
     "msg": "Hello"
   }
}
```

And make the following call to retrieve actions API:
<details><summary>curl</summary>

```
curl --request POST\
  --url 'https://register-svc.osdu.com/api/register/v1/action:retrieve' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common'
  --data '{
            "id": "common:regularheightfield:123456",
            "kind": "common:petrel:regularheightfield:1.0.0",
            "acl": {
                "viewers": ["data.default.viewers@common.osdu.com"],
                "owners": ["data.default.owners@common.osdu.com"]
            },
            "legal": {
                "legaltags": ["common-sample-legaltag"],
                "otherRelevantDataCountries": ["FR","US","CA"]
            },
            "data": {
                "msg": "Hello"
            }
    }'
```
</details>

This will then find all actions whose filter matches your Record. It will then attempt to substitute any template value and also will evaluate the regular expression from the Record into the action. 

Given two matching actions that had a "url" field with these templates
```
        "url": "https://myapp.osdu.com/action/{id}",
and
        "url": "https://myapp.osdu.com/action?text={data.msg}", 
```
Then the response returns all matching actions with the substituted parameters specified:
```
[
  {
    "id": "123-456-abc",
    "name": "Petrel",
    "description": "Opens the given objects project in Petrel PTS",
    "img": "https://mycdn.com/myimg.png",
    "contactEmail": "abc@test.com",
    "url": "https://myapp.osdu.com/action/common:regularheightfield:123456"
  },
  {
    "id": "923-456-abc",
    "name": "myApp2",
    "description": "Does something awesome",
    "img": "https://mycdn.com/myimg2.png",
    "contactEmail": "abc@test.com",
    "url": "https://myapp.osdu.com/action?text=Hello"
  }
]
```

[Back to Table of Contents](#TOC)

## Delete an Action by ID <a name="delete-action"></a>
This API allows deleting an action with a given id.

```
DELETE /api/register/v1/action/{id}
```
<details><summary>curl</summary>

```
curl --request DELETE \
  --url 'https://register-svc.osdu.com/api/register/v1/action/petrel-launch-project' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common' 
```
</details>

[Back to Table of Contents](#TOC)

## Validate action <a name="regex-test"></a>
This API is a helper API method that allows users to validate their action is working as expected, including template and regular expression usage, before they create an action in the system. 

```
POST /api/register/v1/action:test
```

Let's consider the following payload for [Register an Action](#register-action) request example 

<details><summary>curl</summary>

```
curl --request POST \
  --url 'https://register-svc.osdu.com/api/register/v1/action' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common' \
  --data '{
        "id": "petrel-launch-project",
        "name": "Petrel Project",
        "description": "This action launches the Petrel projects landing page that holds the selected data.",
        "url": "https://myapp.osdu.com/action/{data.uri:^(?:[^\/]*(?:\/(?:\/[^\/]*\/?)?)?([^?]+)(?:\??.+)?)$}",
        "img": "https://mycdn.com/img.png",
        "contactEmail": "abc@test.com",
        "filter": {
            "entityType": ["regularheightfield", "project"],
            "source": ["petrel"],
            "version": ["*"]
         }
}'
```
</details>

The above action applies a regular expression of  
```
^(?:[^\/]*(?:\/(?:\/[^\/]*\/?)?)?([^?]+)(?:\??.+)?)$ 
```
onto the data.uri properties value.

This regular expression attempts to extract the path segment out of a URI. But before we register this action, we want to be sure that the specified regular expression is correct and return the expected value from expected payload for a kind. This can be achieved by following API call:


<details><summary>curl</summary>

```
curl --request POST\
  --url 'https://register-svc.osdu.com/api/register/v1/action:test' \
  --header 'authorization: Bearer <JWT>' \
  --header 'content-type: application/json' \
  --header 'data-partition-id: common'
  --data '{
            "action": {
                "id": "petrel-launch-project",
                "name": "Petrel Project",
                "description": "This action launches the Petrel projects landing page that holds the selected data.",
                "url": "https://myapp.osdu.com/action/{data.uri:^(?:[^\\/]*(?:\\/(?:\\/[^\\/]*\\/?)?)?([^?]+)(?:\\??.+)?)$}",
                "img": "https://mycdn.com/img.png",
                "contactEmail": "abc@test.com",
                "filter": {
                    "entityType": ["regularheightfield", "project"],
                    "source": ["petrel"],
                    "version": ["*"]
                }
            },
            "testPayload": {
                "id": "common:regularheightfield:123456",
                "kind": "common:petrel:regularheightfield:1.0.0",
                "data": {
                    "uri": "https://myproj.com/abc123"
                }
            }
    }'
```
</details>

And in this case the Response would be:

```
    {
        "url": "https://myapp.osdu.com/action/abc123",
        "errors": ""
    }
```

In the above example, the regular expression was valid and we see the response append the path of the data.uri property into the action and there are no errors.

However an error is returned if:

- The filter did not match the testPayload
- The regular expression was invalid
- The regular expression failed to extract a value from the test payload.

There is also the possibility that the regular expression extracts a value, but not the one you expected. In this scenario, the API does not return an error, so you need to validate the returned url is formed as you expected after it is mapped into the test payload.

Here are some regular expression registration examples:

| Example regular expression Registration | Example Record | Example Output|
|:---------------------------|:---------------|:--------------|
|`https://myapp.osdu.com/action/{data.uri:^(?:[^\\/]*(?:\\/(?:\\/[^\\/]*\\/?)?)?([^?]+)(?:\\??.+)?)$}`|`"data": {"uri": "https://myproj.com/abc123"}`| `https://myapp.osdu.com/action/abc123`|
|`https://myapp.osdu.com/action?type={kind:^(?:[A-Za-z]+\\:)*([A-Za-z]+)\\:(?:.+)$`|`"kind": "common:petrel:regularheightfield:1.0.0"`| `https://myapp.osdu.com/action?type=regularheightfield`|
|`https://myapp.osdu.com/action/{kind:^(?:[A-Za-z]+\\:)*(.+)}`|`"data": {"kind": "common:petrel:regularheightfield:1.0.0"}`| `https://myapp.osdu.com/action/1.0.0`|
|`https://myapp.osdu.com/action/{id}?type={kind:^(?:[^:]*:){2}([^:]*)}`|`data": {"id": "test-id", kind": "common:petrel:regularheightfield:1.0.0"}`| `https://myapp.osdu.com/action/test-id?type=regularheightfield`|

The regular expression match per record field is capped at a maximum of 2 seconds for performance reasons. Please take a look at the error message for detailed response.

[Back to Table of Contents](#TOC)

306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
## Version info endpoint
For deployment available public `/info` endpoint, which provides build and git related information.
#### Example response:
```json
{
    "groupId": "org.opengroup.osdu",
    "artifactId": "storage-gcp",
    "version": "0.10.0-SNAPSHOT",
    "buildTime": "2021-07-09T14:29:51.584Z",
    "branch": "feature/GONRG-2681_Build_info",
    "commitId": "7777",
    "commitMessage": "Added copyright to version info properties file",
    "connectedOuterServices": [
      {
        "name": "elasticSearch",
        "version":"..."
      },
      {
        "name": "postgresSql",
        "version":"..."
      },
      {
        "name": "redis",
        "version":"..."
      }
    ]
}
```
This endpoint takes information from files, generated by `spring-boot-maven-plugin`,
`git-commit-id-plugin` plugins. Need to specify paths for generated files to matching
properties:
- `version.info.buildPropertiesPath`
- `version.info.gitPropertiesPath`

[Back to table of contents](#TOC)

342
343
344
345
346
347
348
## Current Limitations <a name="limitation"></a>
There are mainly 2 limitations currently:

- Users need to individually register for each data partition they want the action enabled from.
- We don't support a wildcard in the action URL for the partition id. Something like myaction.com/kind?dpid={data-partition-id} may be supported in the future so that the request can be data partition aware.

[Back to Table of Contents](#TOC)