Skip to content

Commit 138e976

Browse files
authored
Migrate url shortener service (#50896) (#52732)
1 parent d6eb7c0 commit 138e976

File tree

16 files changed

+630
-87
lines changed

16 files changed

+630
-87
lines changed

.github/CODEOWNERS

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# GitHub CODEOWNERS definition
2+
# Identify which groups will be pinged by changes to different parts of the codebase.
3+
# For more info, see https://help.github.com/articles/about-codeowners/
4+
5+
# App
6+
/x-pack/legacy/plugins/lens/ @elastic/kibana-app
7+
/x-pack/legacy/plugins/graph/ @elastic/kibana-app
8+
/src/plugins/share/ @elastic/kibana-app
9+
/src/legacy/server/url_shortening/ @elastic/kibana-app
10+
/src/legacy/server/sample_data/ @elastic/kibana-app
11+
12+
# App Architecture
13+
/src/plugins/data/ @elastic/kibana-app-arch
14+
/src/plugins/embeddable/ @elastic/kibana-app-arch
15+
/src/plugins/expressions/ @elastic/kibana-app-arch
16+
/src/plugins/kibana_react/ @elastic/kibana-app-arch
17+
/src/plugins/kibana_utils/ @elastic/kibana-app-arch
18+
/src/plugins/navigation/ @elastic/kibana-app-arch
19+
/src/plugins/ui_actions/ @elastic/kibana-app-arch
20+
/src/plugins/visualizations/ @elastic/kibana-app-arch
21+
/x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
22+
/src/legacy/core_plugins/data/ @elastic/kibana-app-arch
23+
/src/legacy/core_plugins/embeddable_api/ @elastic/kibana-app-arch
24+
/src/legacy/core_plugins/interpreter/ @elastic/kibana-app-arch
25+
/src/legacy/core_plugins/kibana_react/ @elastic/kibana-app-arch
26+
/src/legacy/core_plugins/kibana/public/management/ @elastic/kibana-app-arch
27+
/src/legacy/core_plugins/kibana/server/field_formats/ @elastic/kibana-app-arch
28+
/src/legacy/core_plugins/kibana/server/routes/api/management/ @elastic/kibana-app-arch
29+
/src/legacy/core_plugins/kibana/server/routes/api/suggestions/ @elastic/kibana-app-arch
30+
/src/legacy/core_plugins/visualizations/ @elastic/kibana-app-arch
31+
/src/legacy/server/index_patterns/ @elastic/kibana-app-arch
32+
33+
# APM
34+
/x-pack/legacy/plugins/apm/ @elastic/apm-ui
35+
/x-pack/test/functional/apps/apm/ @elastic/apm-ui
36+
/src/legacy/core_plugins/apm_oss/ @elastic/apm-ui
37+
38+
# Beats
39+
/x-pack/legacy/plugins/beats_management/ @elastic/beats
40+
41+
# Canvas
42+
/x-pack/legacy/plugins/canvas/ @elastic/kibana-canvas
43+
44+
# Logs & Metrics UI
45+
/x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui
46+
/x-pack/legacy/plugins/integrations_manager/ @elastic/epm
47+
48+
# Machine Learning
49+
/x-pack/legacy/plugins/ml/ @elastic/ml-ui
50+
/x-pack/test/functional/apps/machine_learning/ @elastic/ml-ui
51+
/x-pack/test/functional/services/machine_learning/ @elastic/ml-ui
52+
/x-pack/test/functional/services/ml.ts @elastic/ml-ui
53+
# ML team owns the transform plugin, ES team added here for visibility
54+
# because the plugin lives in Kibana's Elasticsearch management section.
55+
/x-pack/legacy/plugins/transform/ @elastic/ml-ui @elastic/es-ui
56+
/x-pack/test/functional/apps/transform/ @elastic/ml-ui
57+
/x-pack/test/functional/services/transform_ui/ @elastic/ml-ui
58+
/x-pack/test/functional/services/transform.ts @elastic/ml-ui
59+
60+
# Operations
61+
/src/dev/ @elastic/kibana-operations
62+
/src/setup_node_env/ @elastic/kibana-operations
63+
/src/optimize/ @elastic/kibana-operations
64+
/packages/*eslint*/ @elastic/kibana-operations
65+
/packages/*babel*/ @elastic/kibana-operations
66+
/packages/kbn-dev-utils*/ @elastic/kibana-operations
67+
/packages/kbn-es/ @elastic/kibana-operations
68+
/packages/kbn-pm/ @elastic/kibana-operations
69+
/packages/kbn-test/ @elastic/kibana-operations
70+
/src/legacy/server/keystore/ @elastic/kibana-operations
71+
/src/legacy/server/pid/ @elastic/kibana-operations
72+
/src/legacy/server/sass/ @elastic/kibana-operations
73+
/src/legacy/server/utils/ @elastic/kibana-operations
74+
/src/legacy/server/warnings/ @elastic/kibana-operations
75+
76+
# Platform
77+
/src/core/ @elastic/kibana-platform
78+
/config/kibana.yml @elastic/kibana-platform
79+
/x-pack/plugins/features/ @elastic/kibana-platform
80+
/x-pack/plugins/licensing/ @elastic/kibana-platform
81+
/packages/kbn-config-schema/ @elastic/kibana-platform
82+
/src/legacy/server/config/ @elastic/kibana-platform
83+
/src/legacy/server/csp/ @elastic/kibana-platform
84+
/src/legacy/server/http/ @elastic/kibana-platform
85+
/src/legacy/server/i18n/ @elastic/kibana-platform
86+
/src/legacy/server/logging/ @elastic/kibana-platform
87+
/src/legacy/server/saved_objects/ @elastic/kibana-platform
88+
/src/legacy/server/status/ @elastic/kibana-platform
89+
90+
# Security
91+
/x-pack/legacy/plugins/security/ @elastic/kibana-security
92+
/x-pack/legacy/plugins/spaces/ @elastic/kibana-security
93+
/x-pack/plugins/spaces/ @elastic/kibana-security
94+
/x-pack/legacy/plugins/encrypted_saved_objects/ @elastic/kibana-security
95+
/x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security
96+
/src/legacy/server/csp/ @elastic/kibana-security
97+
/x-pack/plugins/security/ @elastic/kibana-security
98+
/x-pack/test/api_integration/apis/security/ @elastic/kibana-security
99+
100+
# Kibana Stack Services
101+
/src/dev/i18n @elastic/kibana-stack-services
102+
/packages/kbn-analytics/ @elastic/kibana-stack-services
103+
/src/legacy/core_plugins/ui_metric/ @elastic/kibana-stack-services
104+
/src/plugins/usage_collection/ @elastic/kibana-stack-services
105+
/x-pack/legacy/plugins/telemetry @elastic/kibana-stack-services
106+
/x-pack/legacy/plugins/alerting @elastic/kibana-stack-services
107+
/x-pack/legacy/plugins/actions @elastic/kibana-stack-services
108+
/x-pack/legacy/plugins/task_manager @elastic/kibana-stack-services
109+
110+
# Design
111+
**/*.scss @elastic/kibana-design
112+
113+
# Elasticsearch UI
114+
/src/legacy/core_plugins/console/ @elastic/es-ui
115+
/src/plugins/es_ui_shared/ @elastic/es-ui
116+
/x-pack/legacy/plugins/console_extensions/ @elastic/es-ui
117+
/x-pack/legacy/plugins/cross_cluster_replication/ @elastic/es-ui
118+
/x-pack/legacy/plugins/index_lifecycle_management/ @elastic/es-ui
119+
/x-pack/legacy/plugins/index_management/ @elastic/es-ui
120+
/x-pack/legacy/plugins/license_management/ @elastic/es-ui
121+
/x-pack/legacy/plugins/remote_clusters/ @elastic/es-ui
122+
/x-pack/legacy/plugins/rollup/ @elastic/es-ui
123+
/x-pack/legacy/plugins/searchprofiler/ @elastic/es-ui
124+
/x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui
125+
/x-pack/legacy/plugins/watcher/ @elastic/es-ui
126+
127+
# Kibana TSVB external contractors
128+
/src/legacy/core_plugins/metrics/ @elastic/kibana-tsvb-external

src/legacy/server/url_shortening/routes/create_routes.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919

2020
import { shortUrlLookupProvider } from './lib/short_url_lookup';
2121
import { createGotoRoute } from './goto';
22-
import { createShortenUrlRoute } from './shorten_url';
2322

2423

2524
export function createRoutes(server) {
2625
const shortUrlLookup = shortUrlLookupProvider(server);
2726

2827
server.route(createGotoRoute({ server, shortUrlLookup }));
29-
server.route(createShortenUrlRoute({ shortUrlLookup }));
3028
}

src/legacy/server/url_shortening/routes/goto.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,12 @@ import { shortUrlAssertValid } from './lib/short_url_assert_valid';
2222

2323
export const createGotoRoute = ({ server, shortUrlLookup }) => ({
2424
method: 'GET',
25-
path: '/goto/{urlId}',
25+
path: '/goto_LP/{urlId}',
2626
handler: async function (request, h) {
2727
try {
2828
const url = await shortUrlLookup.getUrl(request.params.urlId, request);
2929
shortUrlAssertValid(url);
3030

31-
const uiSettings = request.getUiSettingsService();
32-
const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage');
33-
if (!stateStoreInSessionStorage) {
34-
return h.redirect(request.getBasePath() + url);
35-
}
36-
3731
const app = server.getHiddenUiAppById('stateSessionStorageRedirect');
3832
return h.renderApp(app, {
3933
redirectUrl: url,

src/legacy/server/url_shortening/routes/lib/short_url_lookup.js

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
* under the License.
1818
*/
1919

20-
import crypto from 'crypto';
2120
import { get } from 'lodash';
2221

2322
export function shortUrlLookupProvider(server) {
@@ -34,29 +33,6 @@ export function shortUrlLookupProvider(server) {
3433
}
3534

3635
return {
37-
async generateUrlId(url, req) {
38-
const id = crypto.createHash('md5').update(url).digest('hex');
39-
const savedObjectsClient = req.getSavedObjectsClient();
40-
const { isConflictError } = savedObjectsClient.errors;
41-
42-
try {
43-
const doc = await savedObjectsClient.create('url', {
44-
url,
45-
accessCount: 0,
46-
createDate: new Date(),
47-
accessDate: new Date()
48-
}, { id });
49-
50-
return doc.id;
51-
} catch (error) {
52-
if (isConflictError(error)) {
53-
return id;
54-
}
55-
56-
throw error;
57-
}
58-
},
59-
6036
async getUrl(id, req) {
6137
const doc = await req.getSavedObjectsClient().get('url', id);
6238
updateMetadata(doc, req);

src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -48,43 +48,6 @@ describe('shortUrlLookupProvider', () => {
4848
sandbox.restore();
4949
});
5050

51-
describe('generateUrlId', () => {
52-
it('returns the document id', async () => {
53-
const id = await shortUrl.generateUrlId(URL, req);
54-
expect(id).toEqual(ID);
55-
});
56-
57-
it('provides correct arguments to savedObjectsClient', async () => {
58-
await shortUrl.generateUrlId(URL, req);
59-
60-
sinon.assert.calledOnce(savedObjectsClient.create);
61-
const [type, attributes, options] = savedObjectsClient.create.getCall(0).args;
62-
63-
expect(type).toEqual(TYPE);
64-
expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate', 'createDate', 'url']);
65-
expect(attributes.url).toEqual(URL);
66-
expect(options.id).toEqual(ID);
67-
});
68-
69-
it('passes persists attributes', async () => {
70-
await shortUrl.generateUrlId(URL, req);
71-
72-
sinon.assert.calledOnce(savedObjectsClient.create);
73-
const [type, attributes] = savedObjectsClient.create.getCall(0).args;
74-
75-
expect(type).toEqual(TYPE);
76-
expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate', 'createDate', 'url']);
77-
expect(attributes.url).toEqual(URL);
78-
});
79-
80-
it('gracefully handles version conflict', async () => {
81-
const error = savedObjectsClient.errors.decorateConflictError(new Error());
82-
savedObjectsClient.create.throws(error);
83-
const id = await shortUrl.generateUrlId(URL, req);
84-
expect(id).toEqual(ID);
85-
});
86-
});
87-
8851
describe('getUrl', () => {
8952
beforeEach(() => {
9053
const attributes = { accessCount: 2, url: URL };

src/plugins/share/kibana.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "share",
33
"version": "kibana",
4-
"server": false,
4+
"server": true,
55
"ui": true
66
}

src/legacy/server/url_shortening/routes/shorten_url.js renamed to src/plugins/share/server/index.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,9 @@
1717
* under the License.
1818
*/
1919

20-
import { handleShortUrlError } from './lib/short_url_error';
21-
import { shortUrlAssertValid } from './lib/short_url_assert_valid';
20+
import { PluginInitializerContext } from '../../../core/server';
21+
import { SharePlugin } from './plugin';
2222

23-
export const createShortenUrlRoute = ({ shortUrlLookup }) => ({
24-
method: 'POST',
25-
path: '/api/shorten_url',
26-
handler: async function (request) {
27-
try {
28-
shortUrlAssertValid(request.payload.url);
29-
const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request);
30-
return { urlId };
31-
} catch (err) {
32-
throw handleShortUrlError(err);
33-
}
34-
}
35-
});
23+
export function plugin(initializerContext: PluginInitializerContext) {
24+
return new SharePlugin(initializerContext);
25+
}

src/plugins/share/server/plugin.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server';
21+
import { createRoutes } from './routes/create_routes';
22+
23+
export class SharePlugin implements Plugin {
24+
constructor(private readonly initializerContext: PluginInitializerContext) {}
25+
26+
public async setup(core: CoreSetup) {
27+
createRoutes(core, this.initializerContext.logger.get());
28+
}
29+
30+
public start() {
31+
this.initializerContext.logger.get().debug('Starting plugin');
32+
}
33+
34+
public stop() {
35+
this.initializerContext.logger.get().debug('Stopping plugin');
36+
}
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { CoreSetup, Logger } from 'kibana/server';
21+
22+
import { shortUrlLookupProvider } from './lib/short_url_lookup';
23+
import { createGotoRoute } from './goto';
24+
import { createShortenUrlRoute } from './shorten_url';
25+
26+
export function createRoutes({ http }: CoreSetup, logger: Logger) {
27+
const shortUrlLookup = shortUrlLookupProvider({ logger });
28+
const router = http.createRouter();
29+
30+
createGotoRoute({ router, shortUrlLookup, http });
31+
createShortenUrlRoute({ router, shortUrlLookup });
32+
}

0 commit comments

Comments
 (0)