egnyte-resellers
Version:
Library for managing things against the undocumented egnyte resellers API.
233 lines (232 loc) • 10.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Customers = void 0;
const index_1 = require("../../index");
const base_1 = require("../base/base");
class Customers extends base_1.Base {
constructor(plans, _config) {
super(_config);
this.plans = plans;
}
async getAllCustomers() {
var _a;
const { authCookie, csrfToken } = await this.authenticate();
const cookie = `${authCookie}; csrftoken=${csrfToken};`;
const planIds = await this.plans._getAllPlanIds(cookie);
const customers = [];
let processedCount = 0;
for (const planId of planIds) {
processedCount++;
let usageStats;
try {
const res = await this.http.get(`/msp/usage_stats/${this.resellerId}/${planId}/`, {
headers: {
cookie: cookie,
'X-CSRFToken': csrfToken,
},
});
usageStats = Array.isArray(res.data) ? res.data : [];
}
catch (error) {
continue;
}
for (const customer of usageStats) {
const entries = Object.entries(customer);
if (entries.length === 0) {
continue;
}
const [customerEgnyteId, ref] = entries[0];
const obj = {
customerEgnyteId,
planId,
powerUsers: this.extractResourceStats(ref.power_user_stats),
storageGB: this.extractResourceStats(ref.storage_stats),
features: this.processFeatures(ref.feature_stats),
};
customers.push(obj);
}
const delay = this.calculateBackoff(processedCount, (_a = this.config.backoffDelay) !== null && _a !== void 0 ? _a : 1000);
await this.delay(delay);
}
return customers;
}
extractResourceStats(stats) {
return {
total: stats.Used + stats.Unused,
used: stats.Used,
available: stats.Available,
free: stats.Unused,
};
}
processFeatures(featureStats) {
const features = {};
for (const [key, value] of Object.entries(featureStats)) {
const typedKey = key;
const mappedKey = index_1.FeatureMap.get(typedKey);
const targetKey = mappedKey || this.toCamelCase(typedKey);
features[targetKey] = value;
}
features.totalStandardUserPacks = Math.ceil((featureStats.additional_su - featureStats.total_power_users) / 5);
return features;
}
calculateBackoff(attempt, baseDelay) {
const maxDelay = 10000;
const calculatedDelay = Math.min(baseDelay * Math.pow(1.5, attempt - 1), maxDelay);
return calculatedDelay;
}
delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async getOneCustomer(customerId) {
const allCustomers = await this.getAllCustomers();
const customer = allCustomers.find((customer) => customer.customerEgnyteId === customerId);
if (!customer)
throw new Error(`unable to find egnyte customer: ${customerId}`);
return customer;
}
async updateCustomer(customerId, data) {
var _a, _b;
const allCustomers = await this.getAllCustomers();
const customer = allCustomers.find((customer) => customer.customerEgnyteId === customerId);
if (!customer)
throw new Error(`unable to find egnyte customer: ${customerId}`);
if (((_a = data === null || data === void 0 ? void 0 : data.powerUsers) === null || _a === void 0 ? void 0 : _a.total) && data.powerUsers.total !== customer.powerUsers.total) {
await this.updateCustomerPowerUsers(customerId, data.powerUsers.total);
customer.powerUsers.total = data.powerUsers.total;
customer.powerUsers.free = data.powerUsers.total - customer.powerUsers.used;
}
if (((_b = data === null || data === void 0 ? void 0 : data.storageGB) === null || _b === void 0 ? void 0 : _b.total) && data.storageGB.total !== customer.storageGB.total) {
await this.updateCustomerStorage(customerId, data.storageGB.total);
customer.storageGB.total = data.storageGB.total;
customer.storageGB.free = data.storageGB.total - customer.storageGB.used;
}
return customer;
}
async updateCustomerStorage(customerId, storageSizeGB) {
customerId = customerId.toLowerCase();
const customer = await this.getOneCustomer(customerId);
if (storageSizeGB < customer.storageGB.used) {
const response = {
result: 'NO_CHANGE',
message: `customerId ${customerId} currently has ${customer.storageGB.used}GB storage in use. Refusing to set to ${storageSizeGB}GB storage.`,
};
return response;
}
else if (storageSizeGB === customer.storageGB.total) {
const response = {
result: 'NO_CHANGE',
message: `customerId ${customerId} is already set to ${storageSizeGB}GB storage. Did not modify.`,
};
return response;
}
const { authCookie, csrfToken } = await this.authenticate();
const response = await this.http.post(`/msp/change_storage/${this.resellerId}/`, {
domain: customerId,
storage: storageSizeGB.toString(),
}, {
headers: {
Cookie: `${authCookie}; csrftoken=${csrfToken}`,
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': csrfToken,
},
});
const result = response.data;
if (result.msg === 'Plan updated successfully!') {
return {
result: 'SUCCESS',
message: `Updated customerId ${customerId} from ${customer.storageGB.total}GB to ${storageSizeGB}GB storage successfully.`,
};
}
else {
throw new Error(result.msg);
}
}
async updateCustomerPowerUsers(customerId, numOfUsers, autoAddToPool) {
customerId = customerId.toLowerCase();
const customer = await this.getOneCustomer(customerId);
if (numOfUsers === customer.powerUsers.total) {
return {
result: 'NO_CHANGE',
message: `customerId ${customerId} is already set to ${numOfUsers} power users. Did not modify.`,
};
}
if (numOfUsers < customer.powerUsers.used && this.config.forceLicenseChange !== true) {
return {
result: 'NO_CHANGE',
message: `customerId ${customerId} currently has ${customer.powerUsers.used} power users in use. Refusing to set to ${numOfUsers} power users.`,
};
}
const licensesNeeded = numOfUsers - customer.powerUsers.total;
if (licensesNeeded > 0 &&
customer.powerUsers.available < licensesNeeded &&
!autoAddToPool) {
throw new Error(`Not enough available licenses on customers reseller plan. Need ${licensesNeeded} but only ${customer.powerUsers.available} are available.`);
}
if (autoAddToPool && licensesNeeded > 0) {
await this.ensureSufficientLicensesInPool(customer.planId, licensesNeeded, customer.powerUsers.available);
}
const { authCookie, csrfToken } = await this.authenticate();
const res = await this.http.post(`/msp/change_power_users/${this.resellerId}/`, {
domain: customerId,
power_users: numOfUsers.toString(),
}, {
headers: {
Cookie: `${authCookie}; csrftoken=${csrfToken}`,
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': csrfToken,
Referer: 'https://resellers.egnyte.com',
},
validateStatus: (status) => (status >= 200 && status <= 303) || status === 400,
});
const result = res.data;
if (result.msg === 'Plan updated successfully!') {
return {
result: 'SUCCESS',
message: `Updated customerId ${customerId} from ${customer.powerUsers.total} to ${numOfUsers} power users successfully.`,
};
}
else if (result.msg === 'CFS plan upgrade failed. Please contact support.' &&
this.config.forceLicenseChange &&
res.status === 400) {
return {
result: 'SUCCESS',
message: `Updated customerId ${customerId} from ${customer.powerUsers.total} to ${numOfUsers} power users successfully with force option.`,
};
}
else {
throw new Error(result.msg || 'Unknown error updating power users');
}
}
async ensureSufficientLicensesInPool(planId, licensesNeeded, availableLicenses) {
if (licensesNeeded <= availableLicenses) {
return;
}
const plans = await this.plans.getPlans();
const plan = plans.find((e) => e.planId === planId);
if (!plan) {
throw new Error(`Could not find plan with ID ${planId}`);
}
const additionalLicensesNeeded = licensesNeeded - availableLicenses;
const licensesToAdd = Math.ceil(additionalLicensesNeeded / 5) * 5;
const updatedLicensesTotal = licensesToAdd + plan.totalPowerUsers;
await this.plans.UpdatePowerUserLicensing(planId, updatedLicensesTotal);
}
async getCustomerProtectPlanUsage(egnyteTenantId) {
const { authCookie, csrfToken } = await this.authenticate();
const { data: protectUsage } = await this.http.get(`/msp/usage_stats/${this.resellerId}/${this.config.protectPlanId}/`, {
headers: { cookie: authCookie, 'X-CSRFToken': csrfToken },
});
const id = `protect${egnyteTenantId.toLowerCase()}`;
for (const entry of protectUsage) {
if (Object.keys(entry)[0] === id) {
return entry[id].storage_stats;
}
}
return null;
}
toCamelCase(str) {
return str.toLowerCase().replace(/[-_][a-z]/g, (group) => group.slice(-1).toUpperCase());
}
}
exports.Customers = Customers;