kibana/x-pack/plugins/spaces/public/spaces_manager/spaces_manager.ts

159 lines
5.1 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Observable, BehaviorSubject } from 'rxjs';
import { skipWhile } from 'rxjs/operators';
import { HttpSetup } from 'src/core/public';
import { SavedObjectsManagementRecord } from 'src/plugins/saved_objects_management/public';
import { Space } from '../../common/model/space';
import { GetAllSpacesPurpose, GetSpaceResult } from '../../common/model/types';
import { CopySavedObjectsToSpaceResponse } from '../copy_saved_objects_to_space/types';
type SavedObject = Pick<SavedObjectsManagementRecord, 'type' | 'id'>;
interface GetAllSpacesOptions {
purpose?: GetAllSpacesPurpose;
includeAuthorizedPurposes?: boolean;
}
export class SpacesManager {
private activeSpace$: BehaviorSubject<Space | null> = new BehaviorSubject<Space | null>(null);
private readonly serverBasePath: string;
public readonly onActiveSpaceChange$: Observable<Space>;
constructor(private readonly http: HttpSetup) {
this.serverBasePath = http.basePath.serverBasePath;
this.onActiveSpaceChange$ = this.activeSpace$
.asObservable()
.pipe(skipWhile((v: Space | null) => v == null)) as Observable<Space>;
this.refreshActiveSpace();
}
public async getSpaces(options: GetAllSpacesOptions = {}): Promise<GetSpaceResult[]> {
const { purpose, includeAuthorizedPurposes } = options;
const query = { purpose, include_authorized_purposes: includeAuthorizedPurposes };
return await this.http.get('/api/spaces/space', { query });
}
public async getSpace(id: string): Promise<Space> {
return await this.http.get(`/api/spaces/space/${encodeURIComponent(id)}`);
}
public getActiveSpace({ forceRefresh = false } = {}) {
if (this.isAnonymousPath()) {
throw new Error(`Cannot retrieve the active space for anonymous paths`);
}
if (!forceRefresh && this.activeSpace$.value) {
return Promise.resolve(this.activeSpace$.value);
}
return this.http.get('/internal/spaces/_active_space') as Promise<Space>;
}
public async createSpace(space: Space) {
await this.http.post(`/api/spaces/space`, {
body: JSON.stringify(space),
});
}
public async updateSpace(space: Space) {
await this.http.put(`/api/spaces/space/${encodeURIComponent(space.id)}`, {
query: {
overwrite: true,
},
body: JSON.stringify(space),
});
const activeSpaceId = (await this.getActiveSpace()).id;
if (space.id === activeSpaceId) {
this.refreshActiveSpace();
}
}
public async deleteSpace(space: Space) {
await this.http.delete(`/api/spaces/space/${encodeURIComponent(space.id)}`);
}
public async copySavedObjects(
objects: SavedObject[],
spaces: string[],
includeReferences: boolean,
createNewCopies: boolean,
overwrite: boolean
): Promise<CopySavedObjectsToSpaceResponse> {
return this.http.post('/api/spaces/_copy_saved_objects', {
body: JSON.stringify({
objects,
spaces,
includeReferences,
createNewCopies,
...(createNewCopies ? { overwrite: false } : { overwrite }), // ignore the overwrite option if createNewCopies is enabled
}),
});
}
public async resolveCopySavedObjectsErrors(
objects: SavedObject[],
retries: unknown,
includeReferences: boolean,
createNewCopies: boolean
): Promise<CopySavedObjectsToSpaceResponse> {
return this.http.post(`/api/spaces/_resolve_copy_saved_objects_errors`, {
body: JSON.stringify({
objects,
includeReferences,
createNewCopies,
retries,
}),
});
}
public async getShareSavedObjectPermissions(
type: string
): Promise<{ shareToAllSpaces: boolean }> {
return this.http
.get('/internal/security/_share_saved_object_permissions', { query: { type } })
.catch((err) => {
const isNotFound = err?.body?.statusCode === 404;
if (isNotFound) {
// security is not enabled
return { shareToAllSpaces: true };
}
throw err;
});
}
public async shareSavedObjectAdd(object: SavedObject, spaces: string[]): Promise<void> {
return this.http.post(`/api/spaces/_share_saved_object_add`, {
body: JSON.stringify({ object, spaces }),
});
}
public async shareSavedObjectRemove(object: SavedObject, spaces: string[]): Promise<void> {
return this.http.post(`/api/spaces/_share_saved_object_remove`, {
body: JSON.stringify({ object, spaces }),
});
}
public redirectToSpaceSelector() {
window.location.href = `${this.serverBasePath}/spaces/space_selector`;
}
private async refreshActiveSpace() {
// Anonymous paths (such as login/logout) should not request the active space under any circumstances.
if (this.isAnonymousPath()) {
return;
}
const activeSpace = await this.getActiveSpace({ forceRefresh: true });
this.activeSpace$.next(activeSpace);
}
private isAnonymousPath() {
return this.http.anonymousPaths.isAnonymous(window.location.pathname);
}
}