@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
207 lines (203 loc) • 7.75 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, Injectable } from '@angular/core';
import * as i1 from '@c8y/client';
import * as i2 from '@c8y/ngx-components';
import { Permissions, ContextRouteService, ViewContext } from '@c8y/ngx-components';
import { gettext } from '@c8y/ngx-components/gettext';
import { defer, shareReplay } from 'rxjs';
const CREDENTIALS_TYPES = {
NONE: {
name: 'NONE',
value: 'NONE',
label: gettext('No password')
},
USER_PASS: {
name: 'USER_PASS',
value: 'USER_PASS',
label: gettext('Username and password')
},
PASS_ONLY: {
name: 'PASS_ONLY',
value: 'PASS_ONLY',
label: gettext('Password only')
},
KEY_PAIR: {
name: 'KEY_PAIR',
value: 'KEY_PAIR',
label: gettext('Public/private keys')
},
CERTIFICATE: {
name: 'CERTIFICATE',
value: 'CERTIFICATE',
label: gettext('Certificate')
}
};
const canActivateRemoteAccess = (route) => {
const permissions = inject(Permissions);
const remoteAccessService = inject(RemoteAccessService);
const contextRouteService = inject(ContextRouteService);
if (!permissions.hasRole(Permissions.ROLE_REMOTE_ACCESS_ADMIN)) {
return false;
}
const contextDetails = contextRouteService.getContextData(route);
if (contextDetails.context !== ViewContext.Device) {
return false;
}
const device = contextDetails.contextData;
if (!device || !Array.isArray(device.c8y_SupportedOperations)) {
return false;
}
const supportedOperations = device.c8y_SupportedOperations;
if (!supportedOperations.includes('c8y_RemoteAccessConnect')) {
return false;
}
return remoteAccessService.isAvailable$();
};
class RemoteAccessService {
constructor(fetchClient, serviceRegistry) {
this.fetchClient = fetchClient;
this.serviceRegistry = serviceRegistry;
this.baseUrl = '/service/remoteaccess';
}
/**
* Verifies if the remote access service is available by sending a HEAD request to is's health endpoint.
* @returns cached Observable that emits true if the service is available, false otherwise.
*/
isAvailable$() {
if (!this.cachedIsAvailable$) {
this.cachedIsAvailable$ = defer(() => this.healthEndpointAvailable()).pipe(shareReplay(1));
}
return this.cachedIsAvailable$;
}
/**
* misses the leading ? for the query params
*/
getAuthQueryParamsForWebsocketConnection() {
const { headers } = this.fetchClient.getFetchOptions();
const params = new URLSearchParams();
if (headers) {
const xsrfToken = headers['X-XSRF-TOKEN'];
const auth = headers['Authorization'];
if (xsrfToken) {
params.append('XSRF-TOKEN', xsrfToken);
}
if (auth) {
params.append('token', auth.replace('Bearer ', '').replace('Basic ', ''));
}
}
const paramsString = params.toString();
return paramsString;
}
/**
* Returns the URI for the websocket connection to the remote access service.
*/
getWebSocketUri(deviceId, configurationId) {
const authQueryParams = this.getAuthQueryParamsForWebsocketConnection();
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss';
const pathName = `${protocol}://${window.location.host}${this.baseUrl}/client/${deviceId}/configurations/${configurationId}`;
return authQueryParams ? `${pathName}?${authQueryParams}` : pathName;
}
/**
* Retrieves all configurations for a given device.
*/
async listConfigurations(deviceId) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations`);
if (response.ok) {
return response.json();
}
throw new Error(`Failed to fetch configurations for device ${deviceId}`);
}
/**
* Deletes a configuration for a given device.
*/
async deleteConfiguration(deviceId, configurationId) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations/${configurationId}`, { method: 'DELETE' });
if (response.ok) {
return;
}
throw new Error(`Failed to delete configuration for device ${deviceId}`);
}
/**
* Retrieves all available remote access protocol providers.
*/
getProtocolProviders() {
return this.serviceRegistry.get('remoteAccessProtocolHook');
}
/**
* Creates a new configuration for a given device.
*/
async addConfiguration(deviceId, configuration) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(configuration)
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to add configuration for device ${configuration.attrs.deviceId}`);
}
/**
* Updates a configuration for a given device.
*/
async updateConfiguration(deviceId, configuration) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/devices/${deviceId}/configurations/${configuration.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(configuration)
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to update configuration for device ${configuration.attrs.deviceId}`);
}
/**
* Generates a SSH key pair for a given hostname.
*/
async generateKeyPair(hostname) {
const response = await this.fetchClient.fetch(`${this.baseUrl}/keypair/generate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ hostname })
});
if (response.ok) {
return response.json();
}
throw new Error(`Failed to generate key pair for ${hostname}`);
}
async healthEndpointAvailable() {
try {
const response = await this.fetchClient.fetch(`${this.baseUrl}/health`, {
method: 'HEAD',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
return !!response.ok;
}
}
catch (e) {
return false;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, deps: [{ token: i1.FetchClient }, { token: i2.ServiceRegistry }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.FetchClient }, { type: i2.ServiceRegistry }] });
/**
* Generated bundle index. Do not edit.
*/
export { CREDENTIALS_TYPES, RemoteAccessService, canActivateRemoteAccess };
//# sourceMappingURL=c8y-ngx-components-remote-access-data.mjs.map