Admin can update tenant's coordinations
ADD
src/assets/server/rest/v1/schemas/tenant/tenant-coordinations-update.json
+{
+ "$id": "tenant-update-coordinations",
+ "title": "Update one Tenant coordinations",
+ "type": "object",
+ "properties": {
+ "id": {
+ "$ref": "tenant#/definitions/id"
+ },
+ "name": {
+ "$ref": "tenant#/definitions/name"
+ },
+ "email": {
+ "$ref": "user#/definitions/email"
+ },
+ "logo": {
+ "$ref": "common#/definitions/logo"
+ },
+ "address": {
+ "$ref": "common#/definitions/address"
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "email"
+ ]
+}

MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -102,6 +102,10 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
admin: {
grants: [
+ {
+ resource: Entity.TENANT, action: [Action.READ, Action.UPDATE],
+ attributes: ['id', 'name', 'email', 'logo', 'address']
+ },
{
resource: Entity.USER,
action: [

MODIFY
src/server/rest/RestServerService.ts
src/server/rest/RestServerService.ts
@@ -167,6 +167,7 @@ class RequestMapper {
// Register REST actions
this.registerJsonActionsPaths({
[ServerAction.TENANT_UPDATE]: TenantService.handleUpdateTenant.bind(this),
+ [ServerAction.TENANT_UPDATE_COORDINATIONS]: TenantService.handleUpdateTenantCoordinations.bind(this),
[ServerAction.SITE_UPDATE]: SiteService.handleUpdateSite.bind(this),
[ServerAction.SITE_AREA_UPDATE]: SiteAreaService.handleUpdateSiteArea.bind(this),
[ServerAction.COMPANY_UPDATE]: CompanyService.handleUpdateCompany.bind(this),

MODIFY
src/server/rest/v1/router/api/TenantRouter.ts
src/server/rest/v1/router/api/TenantRouter.ts
@@ -18,6 +18,7 @@ export default class TenantRouter {
this.buildRouteCreateTenant();
this.buildRouteUpdateTenant();
this.buildRouteDeleteTenant();
+ this.buildRouteUpdateTenantCoordinations();
return this.router;
}
@@ -47,6 +48,13 @@ export default class TenantRouter {
});
}
+ private buildRouteUpdateTenantCoordinations(): void {
+ this.router.put(`/${RESTServerRoute.REST_TENANT_COORDINATIONS}`, (req: Request, res: Response, next: NextFunction) => {
+ req.body.id = req.params.id;
+ void RouterUtils.handleRestServerAction(TenantService.handleUpdateTenantCoordinations.bind(this), ServerAction.TENANT_UPDATE_COORDINATIONS, req, res, next);
+ });
+ }
+
private buildRouteDeleteTenant(): void {
this.router.delete(`/${RESTServerRoute.REST_TENANT}`, (req: Request, res: Response, next: NextFunction) => {
req.query.ID = req.params.id;

MODIFY
src/server/rest/v1/service/TenantService.ts
src/server/rest/v1/service/TenantService.ts
@@ -381,6 +381,46 @@ export default class TenantService {
next();
}
+ public static async handleUpdateTenantCoordinations(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
+ const filteredRequest = TenantValidatorRest.getInstance().validateTenantUpdateCoordinationsReq(req.body);
+ // Check auth
+ if (!await Authorizations.canUpdateTenant(req.user)) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.UPDATE, entity: Entity.TENANT,
+ module: MODULE_NAME, method: 'handleUpdateTenantCoordinations',
+ value: filteredRequest.id
+ });
+ }
+ // Get
+ const tenant = await TenantStorage.getTenant(filteredRequest.id);
+ UtilsService.assertObjectExists(action, tenant, `Tenant ID '${filteredRequest.id}' does not exist`,
+ MODULE_NAME, 'handleUpdateTenantCoordinations', req.user);
+ tenant.name = filteredRequest.name;
+ tenant.address = filteredRequest.address;
+ tenant.components = filteredRequest.components;
+ tenant.email = filteredRequest.email;
+ if (Utils.objectHasProperty(filteredRequest, 'logo')) {
+ tenant.logo = filteredRequest.logo;
+ }
+ // Update timestamp
+ tenant.lastChangedBy = { 'id': req.user.id };
+ tenant.lastChangedOn = new Date();
+ // Update Tenant
+ await TenantStorage.saveTenant(tenant, Utils.objectHasProperty(filteredRequest, 'logo') ? true : false);
+ // Log
+ await Logging.logInfo({
+ tenantID: req.tenant.id, user: req.user,
+ module: MODULE_NAME, method: 'handleUpdateTenantCoordinations',
+ message: `Tenant '${filteredRequest.name}' coordinations has been updated successfully`,
+ action: action,
+ detailedMessages: { tenant }
+ });
+ res.json(Constants.REST_RESPONSE_SUCCESS);
+ next();
+ }
+
private static async updateSettingsWithComponents(tenant: Tenant, req: Request): Promise<void> {
// Create settings
for (const componentName in tenant.components) {

MODIFY
src/server/rest/v1/validator/TenantValidatorRest.ts
src/server/rest/v1/validator/TenantValidatorRest.ts
@@ -12,6 +12,7 @@ export default class TenantValidatorRest extends SchemaValidator {
private static instance: TenantValidatorRest|null = null;
private tenantCreate: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-create.json`, 'utf8'));
private tenantUpdate: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-update.json`, 'utf8'));
+ private tenantUpdateCoordinations: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-coordinations-update.json`, 'utf8'));
private tenantLogoGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-logo-get.json`, 'utf8'));
private tenantGet: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-get.json`, 'utf8'));
private tenantDelete: Schema = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/server/rest/v1/schemas/tenant/tenant-delete.json`, 'utf8'));
@@ -40,6 +41,12 @@ export default class TenantValidatorRest extends SchemaValidator {
return tenant;
}
+ public validateTenantUpdateCoordinationsReq(data: Record<string, unknown>): Tenant {
+ const tenant: Tenant = this.validate(this.tenantUpdateCoordinations, data);
+ this.validateComponentDependencies(tenant);
+ return tenant;
+ }
+
public validateLogoGetReq(data: Record<string, unknown>): HttpTenantLogoGetRequest {
return this.validate(this.tenantLogoGet, data);
}

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -359,6 +359,7 @@ export enum ServerAction {
TENANTS = 'Tenants',
TENANT = 'Tenant',
TENANT_UPDATE = 'TenantUpdate',
+ TENANT_UPDATE_COORDINATIONS = 'TenantUpdateCoordinations',
TENANT_DELETE = 'TenantDelete',
TENANT_LOGO = 'TenantLogo',
@@ -599,6 +600,7 @@ export enum RESTServerRoute {
REST_TENANTS = 'tenants',
REST_TENANT = 'tenants/:id',
+ REST_TENANT_COORDINATIONS = 'tenants/:id/coordinations',
REST_TENANT_LOGO = 'tenants/logo',
REST_COMPANIES = 'companies',

Admin can update tenant's coordinations