UNPKG

7.75 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2018, Kinvey, Inc. All rights reserved.
3 *
4 * This software is licensed to you under the Kinvey terms of service located at
5 * http://www.kinvey.com/terms-of-use. By downloading, accessing and/or using this
6 * software, you hereby accept such terms of service (and any agreement referenced
7 * therein) and agree that you have read, understand and agree to be bound by such
8 * terms of service and are of legal age to agree to such terms with Kinvey.
9 *
10 * This software contains valuable confidential and proprietary information of
11 * KINVEY, INC and is subject to applicable licensing agreements.
12 * Unauthorized reproduction, transmission or distribution of this file and its
13 * contents is a violation of applicable laws.
14 */
15
16const async = require('async');
17
18const { AppOptionsName, DomainTypes, EnvOptionsName, LogLevel, OperationType, OrgOptionsName } = require('./Constants');
19const FileProcessorHelper = require('./FileProcessorHelper');
20const { getObjectByPicking, isEmpty, isNullOrUndefined } = require('./Utils');
21
22class OrgFileProcessor {
23 constructor(options) {
24 this.cliManager = options.cliManager;
25 this.organizationsService = options.organizationsService;
26 this.serviceFileProcessor = options.serviceFileProcessor;
27 this.appFileProcessor = options.appFileProcessor;
28 this.applicationsService = options.applicationsService;
29 this.servicesService = options.servicesService;
30 }
31
32 /**
33 * Processes an org config file.
34 * @param {String} options
35 * @param {Constants.OperationType} options.operation Operation type.
36 * @param {String} options.orgIdentifier Org identifier - ID or name.
37 * @param {Object} options.parsedData Data that will be applied.
38 * @param done
39 */
40 process(options, done) {
41 const operationType = options.operation;
42 const configOrg = options.parsedData;
43 if (operationType !== OperationType.UPDATE) {
44 return setImmediate(() => { done(new Error(`Operation type not supported: ${operationType}`)); });
45 }
46
47 this._updateOrg(configOrg, options, done);
48 }
49
50 _updateOrg(configOrg, options, done) {
51 let fetchedOrg;
52 let groupedServices;
53 let existingServices;
54
55 async.series([
56 (next) => {
57 this.organizationsService.getByIdOrName(options.orgIdentifier, (err, data) => {
58 if (err) {
59 return next(err);
60 }
61
62 fetchedOrg = data;
63 next();
64 });
65 },
66 (next) => {
67 // update org settings
68 const nothingToUpdate = isNullOrUndefined(configOrg.settings) || isNullOrUndefined(configOrg.settings.security)
69 || isEmpty(configOrg.settings.security);
70 if (nothingToUpdate) {
71 return setImmediate(next);
72 }
73
74 this.organizationsService.update(fetchedOrg.id, { security: configOrg.settings.security }, next);
75 },
76 (next) => {
77 this.servicesService.getAllOwnedByOrg(fetchedOrg.id, false, (err, data) => {
78 if (err) {
79 return next(err);
80 }
81
82 existingServices = data;
83 const configServices = configOrg.services || {};
84 groupedServices = FileProcessorHelper.groupEntitiesPerOperationType(existingServices, configServices);
85 next();
86 });
87 },
88 (next) => {
89 this._createServices({ services: groupedServices[OperationType.CREATE], orgId: fetchedOrg.id }, next);
90 },
91 (next) => {
92 this._updateServices({ services: groupedServices[OperationType.UPDATE], existingServices, orgId: fetchedOrg.id }, next);
93 },
94 (next) => {
95 this._modifyApps({ configApps: configOrg.applications, orgId: fetchedOrg.id }, next);
96 }
97 ], (err) => {
98 if (err) {
99 return done(err);
100 }
101
102 done(null, { id: fetchedOrg.id });
103 });
104 }
105
106 /**
107 * Creates services.
108 * @param {Object} options
109 * @param {Object} options.services Services to be created in config format.
110 * @param {String} options.orgId Org ID.
111 * @param done
112 * @private
113 */
114 _createServices(options, done) {
115 if (isNullOrUndefined(options.services) || isEmpty(options.services)) {
116 return setImmediate(done);
117 }
118
119 const servicesNames = Object.keys(options.services);
120 async.eachSeries(
121 servicesNames,
122 (currName, next) => {
123 this.cliManager.log(LogLevel.INFO, `Creating service: ${currName}`);
124 this.serviceFileProcessor.process(
125 {
126 operation: OperationType.CREATE,
127 parsedData: options.services[currName],
128 name: currName,
129 domainId: options.orgId,
130 domainType: DomainTypes.ORG
131 },
132 next
133 );
134 },
135 done
136 );
137 }
138
139 _updateServices(options, done) {
140 const configServices = options.services;
141 if (isEmpty(configServices)) {
142 return setImmediate(done);
143 }
144
145 const existingServices = options.existingServices;
146 const operation = OperationType.UPDATE;
147
148 async.eachSeries(
149 configServices,
150 (currService, next) => {
151 const nameIdentifier = Object.keys(currService)[0];
152 const existingService = existingServices.find(x => x.name === nameIdentifier);
153 const updateData = currService[nameIdentifier];
154 updateData.name = updateData.name || nameIdentifier;
155 const processOptions = {
156 operation,
157 parsedData: updateData,
158 serviceId: existingService.id,
159 domainId: options.orgId,
160 domainType: DomainTypes.ORG
161 };
162 this.cliManager.log(LogLevel.INFO, `Updating service: ${nameIdentifier}`);
163 this.serviceFileProcessor.process(processOptions, next);
164 },
165 done
166 );
167 }
168
169 _createApps({ apps, orgId }, done) {
170 if (isNullOrUndefined(apps) || isEmpty(apps)) {
171 return setImmediate(done);
172 }
173
174 const appNames = Object.keys(apps);
175 async.eachSeries(
176 appNames,
177 (currName, next) => {
178 this.appFileProcessor.process(
179 {
180 operation: OperationType.CREATE,
181 parsedData: apps[currName],
182 name: currName,
183 [OrgOptionsName.ORG]: orgId
184 },
185 next
186 );
187 },
188 done
189 );
190 }
191
192 _updateApps({ apps, existingApps }, done) {
193 if (isNullOrUndefined(apps) || isEmpty(apps)) {
194 return setImmediate(done);
195 }
196
197 async.eachSeries(
198 apps,
199 (currApp, next) => {
200 const nameIdentifier = Object.keys(currApp)[0];
201 const existingApp = existingApps.find(x => x.name === nameIdentifier);
202 const options = {
203 operation: OperationType.UPDATE,
204 parsedData: currApp[nameIdentifier],
205 [AppOptionsName.APP]: existingApp
206 };
207 this.appFileProcessor.process(options, next);
208 },
209 done
210 );
211 }
212
213 _modifyApps({ configApps = {}, orgId }, done) {
214 let existingApps;
215 let groupedApps;
216
217 async.series([
218 (next) => {
219 this.applicationsService.getByOrg(orgId, (err, data) => {
220 if (err) {
221 return next(err);
222 }
223
224 existingApps = data;
225 groupedApps = FileProcessorHelper.groupEntitiesPerOperationType(existingApps, configApps);
226 next();
227 });
228 },
229 (next) => {
230 this._createApps({ apps: groupedApps[OperationType.CREATE], orgId }, next);
231 },
232 (next) => {
233 this._updateApps({ apps: groupedApps[OperationType.UPDATE], existingApps }, next);
234 }
235 ], done);
236 }
237}
238
239module.exports = OrgFileProcessor;