You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
773 lines
23 KiB
773 lines
23 KiB
import { Meteor } from 'meteor/meteor';
|
|
import { HTTP } from 'meteor/http';
|
|
import { fetch } from 'meteor/fetch';
|
|
|
|
import { API } from '../../../api/server';
|
|
import { getUploadFormData } from '../../../api/server/lib/getUploadFormData';
|
|
import { getWorkspaceAccessToken, getUserCloudAccessToken } from '../../../cloud/server';
|
|
import { settings } from '../../../settings/server';
|
|
import { Info } from '../../../utils';
|
|
import { Users } from '../../../models/server';
|
|
import { Settings } from '../../../models/server/raw';
|
|
import { Apps } from '../orchestrator';
|
|
import { formatAppInstanceForRest } from '../../lib/misc/formatAppInstanceForRest';
|
|
import { actionButtonsHandler } from './endpoints/actionButtonsHandler';
|
|
|
|
const appsEngineVersionForMarketplace = Info.marketplaceApiVersion.replace(/-.*/g, '');
|
|
const getDefaultHeaders = () => ({
|
|
'X-Apps-Engine-Version': appsEngineVersionForMarketplace,
|
|
});
|
|
|
|
const purchaseTypes = new Set(['buy', 'subscription']);
|
|
|
|
export class AppsRestApi {
|
|
constructor(orch, manager) {
|
|
this._orch = orch;
|
|
this._manager = manager;
|
|
this.loadAPI();
|
|
}
|
|
|
|
async loadAPI() {
|
|
this.api = new API.ApiClass({
|
|
version: 'apps',
|
|
useDefaultAuth: true,
|
|
prettyJson: false,
|
|
enableCors: false,
|
|
auth: API.getUserAuth(),
|
|
});
|
|
this.addManagementRoutes();
|
|
}
|
|
|
|
addManagementRoutes() {
|
|
const orchestrator = this._orch;
|
|
const manager = this._manager;
|
|
|
|
const handleError = (message, e) => {
|
|
// when there is no `response` field in the error, it means the request
|
|
// couldn't even make it to the server
|
|
if (!e.hasOwnProperty('response')) {
|
|
orchestrator.getRocketChatLogger().warn(message, e.message);
|
|
return API.v1.internalError('Could not reach the Marketplace');
|
|
}
|
|
|
|
orchestrator.getRocketChatLogger().error(message, e.response.data);
|
|
|
|
if (e.response.statusCode >= 500 && e.response.statusCode <= 599) {
|
|
return API.v1.internalError();
|
|
}
|
|
|
|
if (e.response.statusCode === 404) {
|
|
return API.v1.notFound();
|
|
}
|
|
|
|
return API.v1.failure();
|
|
};
|
|
|
|
this.api.addRoute('actionButtons', ...actionButtonsHandler(this));
|
|
|
|
// WE NEED TO MOVE EACH ENDPOINT HANDLER TO IT'S OWN FILE
|
|
this.api.addRoute(
|
|
'',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
// Gets the Apps from the marketplace
|
|
if (this.queryParams.marketplace) {
|
|
const headers = getDefaultHeaders();
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/apps`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
return handleError('Unable to access Marketplace. Does the server has access to the internet?', e);
|
|
}
|
|
|
|
if (!result || result.statusCode !== 200) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the Apps:', result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
return API.v1.success(result.data);
|
|
}
|
|
|
|
if (this.queryParams.categories) {
|
|
const headers = getDefaultHeaders();
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/categories`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the categories from the Marketplace:', e.response.data);
|
|
return API.v1.internalError();
|
|
}
|
|
|
|
if (!result || result.statusCode !== 200) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the categories from the Marketplace:', result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
return API.v1.success(result.data);
|
|
}
|
|
|
|
if (this.queryParams.buildExternalUrl && this.queryParams.appId) {
|
|
const workspaceId = settings.get('Cloud_Workspace_Id');
|
|
|
|
if (!this.queryParams.purchaseType || !purchaseTypes.has(this.queryParams.purchaseType)) {
|
|
return API.v1.failure({ error: 'Invalid purchase type' });
|
|
}
|
|
|
|
const token = getUserCloudAccessToken(this.getLoggedInUser()._id, true, 'marketplace:purchase', false);
|
|
if (!token) {
|
|
return API.v1.failure({ error: 'Unauthorized' });
|
|
}
|
|
|
|
const subscribeRoute = this.queryParams.details === 'true' ? 'subscribe/details' : 'subscribe';
|
|
|
|
const seats = Users.getActiveLocalUserCount();
|
|
|
|
return API.v1.success({
|
|
url: `${baseUrl}/apps/${this.queryParams.appId}/${
|
|
this.queryParams.purchaseType === 'buy' ? this.queryParams.purchaseType : subscribeRoute
|
|
}?workspaceId=${workspaceId}&token=${token}&seats=${seats}`,
|
|
});
|
|
}
|
|
|
|
const apps = manager.get().map(formatAppInstanceForRest);
|
|
|
|
return API.v1.success({ apps });
|
|
},
|
|
async post() {
|
|
let buff;
|
|
let marketplaceInfo;
|
|
let permissionsGranted;
|
|
|
|
if (this.bodyParams.url) {
|
|
if (settings.get('Apps_Framework_Development_Mode') !== true) {
|
|
return API.v1.failure({ error: 'Installation from url is disabled.' });
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(this.bodyParams.url);
|
|
|
|
if (response.status !== 200 || response.headers.get('content-type') !== 'application/zip') {
|
|
return API.v1.failure({
|
|
error: 'Invalid url. It doesn\'t exist or is not "application/zip".',
|
|
});
|
|
}
|
|
|
|
buff = Buffer.from(await response.arrayBuffer());
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the app from url:', e.response.data);
|
|
return API.v1.internalError();
|
|
}
|
|
|
|
if (this.bodyParams.downloadOnly) {
|
|
return API.v1.success({ buff });
|
|
}
|
|
} else if (this.bodyParams.appId && this.bodyParams.marketplace && this.bodyParams.version) {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = getDefaultHeaders();
|
|
try {
|
|
const downloadToken = getWorkspaceAccessToken(true, 'marketplace:download', false);
|
|
const marketplaceToken = getWorkspaceAccessToken();
|
|
|
|
const [downloadResponse, marketplaceResponse] = await Promise.all([
|
|
fetch(`${baseUrl}/v2/apps/${this.bodyParams.appId}/download/${this.bodyParams.version}?token=${downloadToken}`, {
|
|
headers,
|
|
}),
|
|
fetch(`${baseUrl}/v1/apps/${this.bodyParams.appId}?appVersion=${this.bodyParams.version}`, {
|
|
headers: {
|
|
Authorization: `Bearer ${marketplaceToken}`,
|
|
...headers,
|
|
},
|
|
}),
|
|
]);
|
|
|
|
if (downloadResponse.headers.get('content-type') !== 'application/zip') {
|
|
throw new Error('Invalid url. It doesn\'t exist or is not "application/zip".');
|
|
}
|
|
|
|
buff = Buffer.from(await downloadResponse.arrayBuffer());
|
|
marketplaceInfo = await marketplaceResponse.json();
|
|
permissionsGranted = this.bodyParams.permissionsGranted;
|
|
} catch (err) {
|
|
return API.v1.failure(err.message);
|
|
}
|
|
} else {
|
|
if (settings.get('Apps_Framework_Development_Mode') !== true) {
|
|
return API.v1.failure({ error: 'Direct installation of an App is disabled.' });
|
|
}
|
|
|
|
const formData = await getUploadFormData({
|
|
request: this.request,
|
|
});
|
|
buff = formData?.app?.fileBuffer;
|
|
permissionsGranted = (() => {
|
|
try {
|
|
const permissions = JSON.parse(formData?.permissions || '');
|
|
return permissions.length ? permissions : undefined;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
})();
|
|
}
|
|
|
|
if (!buff) {
|
|
return API.v1.failure({ error: 'Failed to get a file to install for the App. ' });
|
|
}
|
|
|
|
const user = orchestrator.getConverters().get('users').convertToApp(Meteor.user());
|
|
|
|
const aff = await manager.add(buff, { marketplaceInfo, permissionsGranted, enable: true, user });
|
|
const info = aff.getAppInfo();
|
|
|
|
if (aff.hasStorageError()) {
|
|
return API.v1.failure({ status: 'storage_error', messages: [aff.getStorageError()] });
|
|
}
|
|
|
|
if (aff.hasAppUserError()) {
|
|
return API.v1.failure({
|
|
status: 'app_user_error',
|
|
messages: [aff.getAppUserError().message],
|
|
payload: { username: aff.getAppUserError().username },
|
|
});
|
|
}
|
|
|
|
info.status = aff.getApp().getStatus();
|
|
|
|
return API.v1.success({
|
|
app: info,
|
|
implemented: aff.getImplementedInferfaces(),
|
|
licenseValidation: aff.getLicenseValidationResult(),
|
|
});
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
'externalComponents',
|
|
{ authRequired: false },
|
|
{
|
|
get() {
|
|
const externalComponents = orchestrator.getProvidedComponents();
|
|
|
|
return API.v1.success({ externalComponents });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
'languages',
|
|
{ authRequired: false },
|
|
{
|
|
get() {
|
|
const apps = manager.get().map((prl) => ({
|
|
id: prl.getID(),
|
|
languages: prl.getStorageItem().languageContent,
|
|
}));
|
|
|
|
return API.v1.success({ apps });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
'externalComponentEvent',
|
|
{ authRequired: true },
|
|
{
|
|
post() {
|
|
if (
|
|
!this.bodyParams.externalComponent ||
|
|
!['IPostExternalComponentOpened', 'IPostExternalComponentClosed'].includes(this.bodyParams.event)
|
|
) {
|
|
return API.v1.failure({ error: 'Event and externalComponent must be provided.' });
|
|
}
|
|
|
|
try {
|
|
const { event, externalComponent } = this.bodyParams;
|
|
const result = Apps.getBridges().getListenerBridge().externalComponentEvent(event, externalComponent);
|
|
|
|
return API.v1.success({ result });
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error(`Error triggering external components' events ${e.response.data}`);
|
|
return API.v1.internalError();
|
|
}
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
'bundles/:id/apps',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = {};
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/bundles/${this.urlParams.id}/apps`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error("Error getting the Bundle's Apps from the Marketplace:", e.response.data);
|
|
return API.v1.internalError();
|
|
}
|
|
|
|
if (!result || result.statusCode !== 200 || result.data.length === 0) {
|
|
orchestrator.getRocketChatLogger().error("Error getting the Bundle's Apps from the Marketplace:", result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
return API.v1.success({ apps: result.data });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
if (this.queryParams.marketplace && this.queryParams.version) {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = {}; // DO NOT ATTACH THE FRAMEWORK/ENGINE VERSION HERE.
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/apps/${this.urlParams.id}?appVersion=${this.queryParams.version}`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
return handleError('Unable to access Marketplace. Does the server has access to the internet?', e);
|
|
}
|
|
|
|
if (!result || result.statusCode !== 200 || result.data.length === 0) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the App information from the Marketplace:', result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
return API.v1.success({ app: result.data[0] });
|
|
}
|
|
|
|
if (this.queryParams.marketplace && this.queryParams.update && this.queryParams.appVersion) {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = getDefaultHeaders();
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/apps/${this.urlParams.id}/latest?frameworkVersion=${appsEngineVersionForMarketplace}`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
return handleError('Unable to access Marketplace. Does the server has access to the internet?', e);
|
|
}
|
|
|
|
if (result.statusCode !== 200 || result.data.length === 0) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the App update info from the Marketplace:', result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
return API.v1.success({ app: result.data });
|
|
}
|
|
const app = manager.getOneById(this.urlParams.id);
|
|
if (!app) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
return API.v1.success({
|
|
app: formatAppInstanceForRest(app),
|
|
});
|
|
},
|
|
async post() {
|
|
let buff;
|
|
let permissionsGranted;
|
|
|
|
if (this.bodyParams.url) {
|
|
if (settings.get('Apps_Framework_Development_Mode') !== true) {
|
|
return API.v1.failure({ error: 'Updating an App from a url is disabled.' });
|
|
}
|
|
|
|
const response = await fetch(this.bodyParams.url);
|
|
|
|
if (response.status !== 200 || response.headers.get('content-type') !== 'application/zip') {
|
|
return API.v1.failure({
|
|
error: 'Invalid url. It doesn\'t exist or is not "application/zip".',
|
|
});
|
|
}
|
|
|
|
buff = Buffer.from(await response.arrayBuffer());
|
|
} else if (this.bodyParams.appId && this.bodyParams.marketplace && this.bodyParams.version) {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = getDefaultHeaders();
|
|
const token = getWorkspaceAccessToken(true, 'marketplace:download', false);
|
|
|
|
try {
|
|
const response = await fetch(
|
|
`${baseUrl}/v2/apps/${this.bodyParams.appId}/download/${this.bodyParams.version}?token=${token}`,
|
|
{
|
|
headers,
|
|
},
|
|
);
|
|
|
|
if (response.status !== 200) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the App from the Marketplace:', await response.text());
|
|
return API.v1.failure();
|
|
}
|
|
|
|
if (response.headers.get('content-type') !== 'application/zip') {
|
|
return API.v1.failure({
|
|
error: 'Invalid url. It doesn\'t exist or is not "application/zip".',
|
|
});
|
|
}
|
|
|
|
buff = Buffer.from(await response.arrayBuffer());
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error('Error getting the App from the Marketplace:', e.response.data);
|
|
return API.v1.internalError();
|
|
}
|
|
} else {
|
|
if (settings.get('Apps_Framework_Development_Mode') !== true) {
|
|
return API.v1.failure({ error: 'Direct updating of an App is disabled.' });
|
|
}
|
|
|
|
const formData = await getUploadFormData({
|
|
request: this.request,
|
|
});
|
|
buff = formData?.app?.fileBuffer;
|
|
permissionsGranted = (() => {
|
|
try {
|
|
const permissions = JSON.parse(formData?.permissions || '');
|
|
return permissions.length ? permissions : undefined;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
})();
|
|
}
|
|
|
|
if (!buff) {
|
|
return API.v1.failure({ error: 'Failed to get a file to install for the App. ' });
|
|
}
|
|
|
|
const aff = await manager.update(buff, permissionsGranted);
|
|
const info = aff.getAppInfo();
|
|
|
|
if (aff.hasStorageError()) {
|
|
return API.v1.failure({ status: 'storage_error', messages: [aff.getStorageError()] });
|
|
}
|
|
|
|
if (aff.hasAppUserError()) {
|
|
return API.v1.failure({
|
|
status: 'app_user_error',
|
|
messages: [aff.getAppUserError().message],
|
|
payload: { username: aff.getAppUserError().username },
|
|
});
|
|
}
|
|
|
|
info.status = aff.getApp().getStatus();
|
|
|
|
return API.v1.success({
|
|
app: info,
|
|
implemented: aff.getImplementedInferfaces(),
|
|
licenseValidation: aff.getLicenseValidationResult(),
|
|
});
|
|
},
|
|
delete() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (!prl) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
const user = orchestrator.getConverters().get('users').convertToApp(Meteor.user());
|
|
|
|
Promise.await(manager.remove(prl.getID(), { user }));
|
|
|
|
const info = prl.getInfo();
|
|
info.status = prl.getStatus();
|
|
|
|
return API.v1.success({ app: info });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/sync',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
post() {
|
|
const baseUrl = orchestrator.getMarketplaceUrl();
|
|
|
|
const headers = getDefaultHeaders();
|
|
const token = getWorkspaceAccessToken();
|
|
if (token) {
|
|
headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
|
|
const workspaceIdSetting = Promise.await(Settings.findOneById('Cloud_Workspace_Id'));
|
|
|
|
let result;
|
|
try {
|
|
result = HTTP.get(`${baseUrl}/v1/workspaces/${workspaceIdSetting.value}/apps/${this.urlParams.id}`, {
|
|
headers,
|
|
});
|
|
} catch (e) {
|
|
orchestrator.getRocketChatLogger().error('Error syncing the App from the Marketplace:', e.response.data);
|
|
return API.v1.internalError();
|
|
}
|
|
|
|
if (result.statusCode !== 200) {
|
|
orchestrator.getRocketChatLogger().error('Error syncing the App from the Marketplace:', result.data);
|
|
return API.v1.failure();
|
|
}
|
|
|
|
Promise.await(Apps.updateAppsMarketplaceInfo([result.data]));
|
|
|
|
return API.v1.success({ app: result.data });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/icon',
|
|
{ authRequired: false },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
if (!prl) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
const info = prl.getInfo();
|
|
if (!info || !info.iconFileContent) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
const imageData = info.iconFileContent.split(';base64,');
|
|
|
|
const buf = Buffer.from(imageData[1], 'base64');
|
|
|
|
return {
|
|
statusCode: 200,
|
|
headers: {
|
|
'Content-Length': buf.length,
|
|
'Content-Type': imageData[0].replace('data:', ''),
|
|
},
|
|
body: buf,
|
|
};
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/languages',
|
|
{ authRequired: false },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (prl) {
|
|
const languages = prl.getStorageItem().languageContent || {};
|
|
|
|
return API.v1.success({ languages });
|
|
}
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/logs',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (prl) {
|
|
const { offset, count } = this.getPaginationItems();
|
|
const { sort, fields, query } = this.parseJsonQuery();
|
|
|
|
const ourQuery = Object.assign({}, query, { appId: prl.getID() });
|
|
const options = {
|
|
sort: sort || { _updatedAt: -1 },
|
|
skip: offset,
|
|
limit: count,
|
|
fields,
|
|
};
|
|
|
|
const logs = Promise.await(orchestrator.getLogStorage().find(ourQuery, options));
|
|
|
|
return API.v1.success({ logs });
|
|
}
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/settings',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (prl) {
|
|
const settings = Object.assign({}, prl.getStorageItem().settings);
|
|
|
|
Object.keys(settings).forEach((k) => {
|
|
if (settings[k].hidden) {
|
|
delete settings[k];
|
|
}
|
|
});
|
|
|
|
return API.v1.success({ settings });
|
|
}
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
},
|
|
post() {
|
|
if (!this.bodyParams || !this.bodyParams.settings) {
|
|
return API.v1.failure('The settings to update must be present.');
|
|
}
|
|
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (!prl) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
const { settings } = prl.getStorageItem();
|
|
|
|
const updated = [];
|
|
this.bodyParams.settings.forEach((s) => {
|
|
if (settings[s.id]) {
|
|
Promise.await(manager.getSettingsManager().updateAppSetting(this.urlParams.id, s));
|
|
// Updating?
|
|
updated.push(s);
|
|
}
|
|
});
|
|
|
|
return API.v1.success({ updated });
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/settings/:settingId',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
try {
|
|
const setting = manager.getSettingsManager().getAppSetting(this.urlParams.id, this.urlParams.settingId);
|
|
|
|
API.v1.success({ setting });
|
|
} catch (e) {
|
|
if (e.message.includes('No setting found')) {
|
|
return API.v1.notFound(`No Setting found on the App by the id of: "${this.urlParams.settingId}"`);
|
|
}
|
|
if (e.message.includes('No App found')) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
return API.v1.failure(e.message);
|
|
}
|
|
},
|
|
post() {
|
|
if (!this.bodyParams.setting) {
|
|
return API.v1.failure('Setting to update to must be present on the posted body.');
|
|
}
|
|
|
|
try {
|
|
Promise.await(manager.getSettingsManager().updateAppSetting(this.urlParams.id, this.bodyParams.setting));
|
|
|
|
return API.v1.success();
|
|
} catch (e) {
|
|
if (e.message.includes('No setting found')) {
|
|
return API.v1.notFound(`No Setting found on the App by the id of: "${this.urlParams.settingId}"`);
|
|
}
|
|
if (e.message.includes('No App found')) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
return API.v1.failure(e.message);
|
|
}
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/apis',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (prl) {
|
|
return API.v1.success({
|
|
apis: manager.apiManager.listApis(this.urlParams.id),
|
|
});
|
|
}
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
},
|
|
},
|
|
);
|
|
|
|
this.api.addRoute(
|
|
':id/status',
|
|
{ authRequired: true, permissionsRequired: ['manage-apps'] },
|
|
{
|
|
get() {
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (prl) {
|
|
return API.v1.success({ status: prl.getStatus() });
|
|
}
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
},
|
|
post() {
|
|
if (!this.bodyParams.status || typeof this.bodyParams.status !== 'string') {
|
|
return API.v1.failure('Invalid status provided, it must be "status" field and a string.');
|
|
}
|
|
|
|
const prl = manager.getOneById(this.urlParams.id);
|
|
|
|
if (!prl) {
|
|
return API.v1.notFound(`No App found by the id of: ${this.urlParams.id}`);
|
|
}
|
|
|
|
const result = Promise.await(manager.changeStatus(prl.getID(), this.bodyParams.status));
|
|
|
|
return API.v1.success({ status: result.getStatus() });
|
|
},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|