@webiny/api-tenancy-so-ddb
Version:
Security storage operations.
286 lines (280 loc) • 7.48 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createStorageOperations = void 0;
var _dbDynamodb = require("@webiny/db-dynamodb");
var _query = require("@webiny/db-dynamodb/utils/query");
var _error = _interopRequireDefault(require("@webiny/error"));
var _table = require("./definitions/table");
var _tenantEntity = require("./definitions/tenantEntity");
var _systemEntity = require("./definitions/systemEntity");
var _domainEntity = require("./definitions/domainEntity");
var _types = require("./types");
const setTenantDefaults = item => {
if (!item.tags) {
item.tags = [];
}
if (!item.description) {
item.description = "";
}
return item;
};
const createStorageOperations = params => {
const {
table,
documentClient
} = params;
const tableInstance = (0, _table.createTable)({
table,
documentClient
});
const entities = {
tenants: (0, _tenantEntity.createTenantEntity)({
entityName: _types.ENTITIES.TENANT,
table: tableInstance
}),
domains: (0, _domainEntity.createDomainEntity)({
entityName: _types.ENTITIES.DOMAIN,
table: tableInstance
}),
system: (0, _systemEntity.createSystemEntity)({
entityName: _types.ENTITIES.SYSTEM,
table: tableInstance
})
};
const systemKeys = {
PK: "T#root#SYSTEM",
SK: "TENANCY"
};
const createNewDomainsRecords = (tenant, existingDomains = []) => {
return tenant.settings.domains.map(({
fqdn
}) => {
// If domain is already in the DB, skip it.
if (existingDomains.find(d => d.fqdn === fqdn)) {
return null;
}
// Add a new domain.
return {
PK: `DOMAIN#${fqdn}`,
SK: `A`,
GSI1_PK: `DOMAINS`,
GSI1_SK: `T#${tenant.id}#${fqdn}`,
tenant: tenant.id,
fqdn,
webinyVersion: tenant.webinyVersion
};
}).filter(Boolean);
};
return {
getTable() {
return tableInstance;
},
getEntities() {
return entities;
},
async createSystemData(data) {
try {
await (0, _dbDynamodb.put)({
entity: entities.system,
item: {
...data,
...systemKeys
}
});
return data;
} catch (err) {
throw _error.default.from(err, {
message: "Could not create system record.",
code: "CREATE_SYSTEM_ERROR",
data: {
keys: systemKeys,
data
}
});
}
},
async getSystemData() {
try {
return await (0, _dbDynamodb.getClean)({
entity: entities.system,
keys: systemKeys
});
} catch (err) {
throw _error.default.from(err, {
message: "Could not load system record.",
code: "GET_SYSTEM_ERROR",
data: {
keys: systemKeys
}
});
}
},
async updateSystemData(data) {
try {
await (0, _dbDynamodb.put)({
entity: entities.system,
item: {
...data,
...systemKeys
}
});
return data;
} catch (err) {
throw _error.default.from(err, {
message: "Could not update system record.",
code: "UPDATE_SYSTEM_ERROR",
data: {
keys: systemKeys,
data
}
});
}
},
async getTenantsByIds(ids) {
const items = ids.map(id => entities.tenants.getBatch({
PK: `T#${id}`,
SK: "A"
}));
const tenants = await (0, _dbDynamodb.batchReadAll)({
table: tableInstance,
items
});
return tenants.map(item => item.data).map(item => setTenantDefaults(item));
},
async listTenants(params = {}) {
const {
parent
} = params;
const options = {
index: "GSI1"
};
if (parent) {
options.beginsWith = `T#${parent}#`;
} else {
options.gt = " ";
}
const tenants = await (0, _query.queryAll)({
entity: entities.tenants,
partitionKey: `TENANTS`,
options
});
return tenants.map(item => item.data).map(item => setTenantDefaults(item));
},
async createTenant(data) {
const keys = {
PK: `T#${data.id}`,
SK: "A",
GSI1_PK: "TENANTS",
GSI1_SK: `T#${data.parent}#${data.createdOn}`
};
try {
const tableWrite = (0, _dbDynamodb.createTableWriteBatch)({
table: tableInstance
});
tableWrite.put(entities.tenants, {
TYPE: "tenancy.tenant",
...keys,
data
});
const newDomains = createNewDomainsRecords(data);
for (const domain of newDomains) {
tableWrite.put(entities.domains, domain);
}
await tableWrite.execute();
return data;
} catch (err) {
throw _error.default.from(err, {
message: "Could not create tenant record.",
code: "CREATE_TENANT_ERROR",
data: {
keys,
data
}
});
}
},
async updateTenant(data) {
const tenantPK = `T#${data.id}`;
const keys = {
PK: tenantPK,
SK: "A",
GSI1_PK: "TENANTS",
GSI1_SK: `T#${data.parent}#${data.createdOn}`
};
const existingDomains = await (0, _query.queryAll)({
entity: entities.domains,
partitionKey: "DOMAINS",
options: {
index: "GSI1",
beginsWith: `T#${data.id}`
}
});
const newDomains = createNewDomainsRecords(data, existingDomains);
const tableWrite = (0, _dbDynamodb.createTableWriteBatch)({
table: tableInstance
});
tableWrite.put(entities.tenants, {
...keys,
data
});
// Delete domains that are in the DB but are NOT in the settings.
for (const {
fqdn
} of existingDomains) {
if (data.settings.domains.some(d => d.fqdn === fqdn)) {
continue;
}
tableWrite.delete(entities.domains, {
PK: `DOMAIN#${fqdn}`,
SK: `A`
});
}
for (const domain of newDomains) {
tableWrite.put(entities.domains, domain);
}
try {
await tableWrite.execute();
return data;
} catch (err) {
throw _error.default.from(err, {
message: "Could not update tenant record.",
code: "CREATE_TENANT_ERROR",
data: {
keys,
data
}
});
}
},
async deleteTenant(id) {
const existingDomains = await (0, _query.queryAll)({
entity: entities.domains,
partitionKey: "DOMAINS",
options: {
index: "GSI1",
beginsWith: `T#${id}`
}
});
const batchWrite = (0, _dbDynamodb.createEntityWriteBatch)({
entity: entities.tenants,
delete: [{
PK: `T#${id}`,
SK: "A"
}]
});
for (const domain of existingDomains) {
batchWrite.delete({
PK: domain.PK,
SK: domain.SK
});
}
// Delete tenant and domain items
await batchWrite.execute();
}
};
};
exports.createStorageOperations = createStorageOperations;
//# sourceMappingURL=index.js.map