Skip to content

Commit

Permalink
Add enhancements for legacy URL aliases (#125960)
Browse files Browse the repository at this point in the history
  • Loading branch information
jportner authored Mar 18, 2022
1 parent fe34af7 commit 4920ace
Show file tree
Hide file tree
Showing 105 changed files with 936 additions and 499 deletions.
25 changes: 18 additions & 7 deletions docs/api/saved-objects/bulk_resolve.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,24 @@ The API returns the following:

Only the index pattern exists, the dashboard was not found.

The `outcome` field may be any of the following:

* `"exactMatch"` -- One document exactly matched the given ID, *or* {kib} failed to find this object.
* `"aliasMatch"` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different than the given ID.
* `"conflict"` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the `saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID.

If the outcome is `"aliasMatch"` or `"conflict"`, the response will also include an `alias_target_id` field. This means that an alias was found for another object, and it describes that other object's ID.
[NOTE]
====
In addition to `saved_object`, several fields can be returned:
* `outcome` (required string) -- One of the following values:
- `"exactMatch"` -- One document exactly matched the given ID.
- `"aliasMatch"` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different than
the given ID.
- `"conflict"` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the
`saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID.
* `alias_target_id` (optional string) -- If the `outcome` is `"aliasMatch"` or `"conflict"`, the response will also include the
`alias_target_id` field. This means that an alias was found for another object, and it describes that other object's ID.
* `alias_purpose` (optional string) -- If the `outcome` is `"aliasMatch"` or `"conflict"`, the response will also include the
`alias_purpose` field. This indicates why the alias was created, and it can be used to change the client behavior accordingly. One of the
following values: `"savedObjectConversion"`, `"savedObjectImport"`
Client-side code uses these fields to behave differently depending on the `outcome` -- <<sharing-saved-objects-step-3,learn more>>.
====

Retrieve a dashboard object in the `testspace` by ID:

Expand Down
25 changes: 18 additions & 7 deletions docs/api/saved-objects/resolve.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,24 @@ The API returns the following:
}
--------------------------------------------------

The `outcome` field may be any of the following:

* `"exactMatch"` -- One document exactly matched the given ID.
* `"aliasMatch"` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different than the given ID.
* `"conflict"` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the `saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID.

If the outcome is `"aliasMatch"` or `"conflict"`, the response will also include an `alias_target_id` field. This means that an alias was found for another object, and it describes that other object's ID.
[NOTE]
====
In addition to `saved_object`, several fields can be returned:
* `outcome` (required string) -- One of the following values:
- `"exactMatch"` -- One document exactly matched the given ID.
- `"aliasMatch"` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different than
the given ID.
- `"conflict"` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the
`saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID.
* `alias_target_id` (optional string) -- If the `outcome` is `"aliasMatch"` or `"conflict"`, the response will also include the
`alias_target_id` field. This means that an alias was found for another object, and it describes that other object's ID.
* `alias_purpose` (optional string) -- If the `outcome` is `"aliasMatch"` or `"conflict"`, the response will also include the
`alias_purpose` field. This indicates why the alias was created, and it can be used to change the client behavior accordingly. One of the
following values: `"savedObjectConversion"`, `"savedObjectImport"`
Client-side code uses these fields to behave differently depending on the `outcome` -- <<sharing-saved-objects-step-3,learn more>>.
====

Retrieve a dashboard object in the `testspace` by ID:

Expand Down
15 changes: 11 additions & 4 deletions docs/developer/advanced/sharing-saved-objects.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,13 @@ TIP: See an example of this in https://github.com/elastic/kibana/pull/107256#use

The
https://github.com/elastic/kibana/blob/main/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveresponse.md[SavedObjectsResolveResponse
interface] has three fields, summarized below:
interface] has four fields, summarized below:

* `saved_object` - The saved object that was found.
* `outcome` - One of the following values: `'exactMatch' | 'aliasMatch' | 'conflict'`
* `alias_target_id` - This is defined if the outcome is `'aliasMatch'` or `'conflict'`. It means that a legacy URL alias with this ID points
to an object with a _different_ ID.
* `alias_purpose` - This is defined if the outcome is `'aliasMatch'` or `'conflict'`. It describes why the legacy URL alis was created.

The SavedObjectsClient is available both on the server-side and the client-side. You may be fetching the object on the server-side via a
custom HTTP route, or you may be fetching it on the client-side directly. Either way, the `outcome` and `alias_target_id` fields need to be
Expand Down Expand Up @@ -236,12 +237,18 @@ if (spacesApi && resolveResult.outcome === 'aliasMatch') {
// We found this object by a legacy URL alias from its old ID; redirect the user to the page with its new ID, preserving any URL hash
const newObjectId = resolveResult.alias_target_id!; // This is always defined if outcome === 'aliasMatch'
const newPath = `/this/page/${newObjectId}${window.location.hash}`; // Use the *local* path within this app (do not include the "/app/appId" prefix)
await spacesApi.ui.redirectLegacyUrl(newPath, OBJECT_NOUN);
await spacesApi.ui.redirectLegacyUrl({
path: newPath,
aliasPurpose: resolveResult.alias_purpose, <1>
objectNoun: OBJECT_NOUN <2>
});
return;
}
```
_Note that `OBJECT_NOUN` is optional, it just changes "object" in the toast to whatever you specify -- you may want the toast to say
"dashboard" or "index pattern" instead!_
<1> The `aliasPurpose` field is required as of 8.2, because the API response now includes the reason the alias was created to inform the
client whether a toast should be shown or not.
<2> The `objectNoun` field is optional, it just changes "object" in the toast to whatever you specify -- you may want the toast to say
"dashboard" or "index pattern" instead!

5. And finally, in your deep link page, add a function that will create a callout in the case of a `'conflict'` outcome:
+
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [ResolvedSimpleSavedObject](./kibana-plugin-core-public.resolvedsimplesavedobject.md) &gt; [alias\_purpose](./kibana-plugin-core-public.resolvedsimplesavedobject.alias_purpose.md)

## ResolvedSimpleSavedObject.alias\_purpose property

The reason this alias was created.

Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

```typescript
alias_purpose?: SavedObjectsResolveResponse['alias_purpose'];
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

## ResolvedSimpleSavedObject.alias\_target\_id property

The ID of the object that the legacy URL alias points to. This is only defined when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->.
The ID of the object that the legacy URL alias points to.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export interface ResolvedSimpleSavedObject<T = unknown>

| Property | Type | Description |
| --- | --- | --- |
| [alias\_target\_id?](./kibana-plugin-core-public.resolvedsimplesavedobject.alias_target_id.md) | SavedObjectsResolveResponse\['alias\_target\_id'\] | <i>(Optional)</i> The ID of the object that the legacy URL alias points to. This is only defined when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>. |
| [alias\_purpose?](./kibana-plugin-core-public.resolvedsimplesavedobject.alias_purpose.md) | SavedObjectsResolveResponse\['alias\_purpose'\] | <i>(Optional)</i> The reason this alias was created.<!-- -->Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [alias\_target\_id?](./kibana-plugin-core-public.resolvedsimplesavedobject.alias_target_id.md) | SavedObjectsResolveResponse\['alias\_target\_id'\] | <i>(Optional)</i> The ID of the object that the legacy URL alias points to.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [outcome](./kibana-plugin-core-public.resolvedsimplesavedobject.outcome.md) | SavedObjectsResolveResponse\['outcome'\] | The outcome for a successful <code>resolve</code> call is one of the following values:<!-- -->\* <code>'exactMatch'</code> -- One document exactly matched the given ID. \* <code>'aliasMatch'</code> -- One document with a legacy URL alias matched the given ID; in this case the <code>saved_object.id</code> field is different than the given ID. \* <code>'conflict'</code> -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the <code>saved_object</code> object is the exact match, and the <code>saved_object.id</code> field is the same as the given ID. |
| [saved\_object](./kibana-plugin-core-public.resolvedsimplesavedobject.saved_object.md) | SimpleSavedObject&lt;T&gt; | The saved object that was found. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsResolveResponse](./kibana-plugin-core-public.savedobjectsresolveresponse.md) &gt; [alias\_purpose](./kibana-plugin-core-public.savedobjectsresolveresponse.alias_purpose.md)

## SavedObjectsResolveResponse.alias\_purpose property

The reason this alias was created.

Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

```typescript
alias_purpose?: 'savedObjectConversion' | 'savedObjectImport';
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

## SavedObjectsResolveResponse.alias\_target\_id property

The ID of the object that the legacy URL alias points to. This is only defined when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->.
The ID of the object that the legacy URL alias points to.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export interface SavedObjectsResolveResponse<T = unknown>

| Property | Type | Description |
| --- | --- | --- |
| [alias\_target\_id?](./kibana-plugin-core-public.savedobjectsresolveresponse.alias_target_id.md) | string | <i>(Optional)</i> The ID of the object that the legacy URL alias points to. This is only defined when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>. |
| [alias\_purpose?](./kibana-plugin-core-public.savedobjectsresolveresponse.alias_purpose.md) | 'savedObjectConversion' \| 'savedObjectImport' | <i>(Optional)</i> The reason this alias was created.<!-- -->Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [alias\_target\_id?](./kibana-plugin-core-public.savedobjectsresolveresponse.alias_target_id.md) | string | <i>(Optional)</i> The ID of the object that the legacy URL alias points to.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [outcome](./kibana-plugin-core-public.savedobjectsresolveresponse.outcome.md) | 'exactMatch' \| 'aliasMatch' \| 'conflict' | The outcome for a successful <code>resolve</code> call is one of the following values:<!-- -->\* <code>'exactMatch'</code> -- One document exactly matched the given ID. \* <code>'aliasMatch'</code> -- One document with a legacy URL alias matched the given ID; in this case the <code>saved_object.id</code> field is different than the given ID. \* <code>'conflict'</code> -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the <code>saved_object</code> object is the exact match, and the <code>saved_object.id</code> field is the same as the given ID. |
| [saved\_object](./kibana-plugin-core-public.savedobjectsresolveresponse.saved_object.md) | SavedObject&lt;T&gt; | The saved object that was found. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsResolveResponse](./kibana-plugin-core-server.savedobjectsresolveresponse.md) &gt; [alias\_purpose](./kibana-plugin-core-server.savedobjectsresolveresponse.alias_purpose.md)

## SavedObjectsResolveResponse.alias\_purpose property

The reason this alias was created.

Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

```typescript
alias_purpose?: 'savedObjectConversion' | 'savedObjectImport';
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

## SavedObjectsResolveResponse.alias\_target\_id property

The ID of the object that the legacy URL alias points to. This is only defined when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->.
The ID of the object that the legacy URL alias points to.

\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is `'aliasMatch'` or `'conflict'`<!-- -->).

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export interface SavedObjectsResolveResponse<T = unknown>

| Property | Type | Description |
| --- | --- | --- |
| [alias\_target\_id?](./kibana-plugin-core-server.savedobjectsresolveresponse.alias_target_id.md) | string | <i>(Optional)</i> The ID of the object that the legacy URL alias points to. This is only defined when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>. |
| [alias\_purpose?](./kibana-plugin-core-server.savedobjectsresolveresponse.alias_purpose.md) | 'savedObjectConversion' \| 'savedObjectImport' | <i>(Optional)</i> The reason this alias was created.<!-- -->Currently this is used to determine whether or not a toast should be shown when a user is redirected from a legacy URL; if the alias was created because of saved object conversion, then we will display a toast telling the user that the object has a new URL.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [alias\_target\_id?](./kibana-plugin-core-server.savedobjectsresolveresponse.alias_target_id.md) | string | <i>(Optional)</i> The ID of the object that the legacy URL alias points to.<!-- -->\*\*Note:\*\* this field is \*only\* included when an alias was found (in other words, when the outcome is <code>'aliasMatch'</code> or <code>'conflict'</code>). |
| [outcome](./kibana-plugin-core-server.savedobjectsresolveresponse.outcome.md) | 'exactMatch' \| 'aliasMatch' \| 'conflict' | The outcome for a successful <code>resolve</code> call is one of the following values:<!-- -->\* <code>'exactMatch'</code> -- One document exactly matched the given ID. \* <code>'aliasMatch'</code> -- One document with a legacy URL alias matched the given ID; in this case the <code>saved_object.id</code> field is different than the given ID. \* <code>'conflict'</code> -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the <code>saved_object</code> object is the exact match, and the <code>saved_object.id</code> field is the same as the given ID. |
| [saved\_object](./kibana-plugin-core-server.savedobjectsresolveresponse.saved_object.md) | SavedObject&lt;T&gt; | The saved object that was found. |

Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ Given a saved object type and id, generates the compound id that is stored in th
<b>Signature:</b>

```typescript
generateRawLegacyUrlAliasId(namespace: string, type: string, id: string): string;
generateRawLegacyUrlAliasId(namespace: string | undefined, type: string, id: string): string;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| namespace | string | The namespace of the saved object |
| namespace | string \| undefined | The namespace of the saved object |
| type | string | The saved object type |
| id | string | The id of the saved object |

Expand Down
2 changes: 2 additions & 0 deletions src/core/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,7 @@ export type ResolveDeprecationResponse = {

// @public
export interface ResolvedSimpleSavedObject<T = unknown> {
alias_purpose?: SavedObjectsResolveResponse['alias_purpose'];
alias_target_id?: SavedObjectsResolveResponse['alias_target_id'];
outcome: SavedObjectsResolveResponse['outcome'];
saved_object: SimpleSavedObject<T>;
Expand Down Expand Up @@ -1347,6 +1348,7 @@ export type SavedObjectsNamespaceType = 'single' | 'multiple' | 'multiple-isolat

// @public (undocumented)
export interface SavedObjectsResolveResponse<T = unknown> {
alias_purpose?: 'savedObjectConversion' | 'savedObjectImport';
alias_target_id?: string;
outcome: 'exactMatch' | 'aliasMatch' | 'conflict';
saved_object: SavedObject<T>;
Expand Down
1 change: 1 addition & 0 deletions src/core/public/saved_objects/saved_objects_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ export class SavedObjectsClient {
saved_object: simpleSavedObject,
outcome: resolveResponse.outcome,
alias_target_id: resolveResponse.alias_target_id,
alias_purpose: resolveResponse.alias_purpose,
};
}

Expand Down
Loading

0 comments on commit 4920ace

Please sign in to comment.