Change handleUpdateSite logic
MODIFY
src/authorization/DynamicAuthorizationFactory.ts
src/authorization/DynamicAuthorizationFactory.ts
@@ -6,6 +6,8 @@ import AssignedSitesDynamicAuthorizationDataSource from './dynamic-data-source/A
import AssignedSitesDynamicAuthorizationFilter from './dynamic-filters/AssignedSitesDynamicAuthorizationFilter';
import DynamicAuthorizationDataSource from './DynamicAuthorizationDataSource';
import DynamicAuthorizationFilter from './DynamicAuthorizationFilter';
+import SitesAdminDynamicAuthorizationDataSource from './dynamic-data-source/SitesAdminDynamicAuthorizationDataSource';
+import SitesAdminDynamicAuthorizationFilter from './dynamic-filters/SitesAdminDynamicAuthorizationFilter';
import Tenant from '../types/Tenant';
import UserToken from '../types/UserToken';
@@ -22,6 +24,9 @@ export default class DynamicAuthorizationFactory {
case DynamicAuthorizationFilterName.ASSIGNED_SITES:
dynamicFilter = new AssignedSitesDynamicAuthorizationFilter(tenant, userToken);
break;
+ case DynamicAuthorizationFilterName.SITES_ADMIN:
+ dynamicFilter = new SitesAdminDynamicAuthorizationFilter(tenant, userToken);
+ break;
}
// Init Data Source
if (dynamicFilter) {
@@ -58,6 +63,8 @@ export default class DynamicAuthorizationFactory {
return new AssignedSitesCompaniesDynamicAuthorizationDataSource(tenant, user);
case DynamicAuthorizationDataSourceName.ASSIGNED_SITES:
return new AssignedSitesDynamicAuthorizationDataSource(tenant, user);
+ case DynamicAuthorizationDataSourceName.SITES_ADMIN:
+ return new SitesAdminDynamicAuthorizationDataSource(tenant, user);
}
}
}

ADD
src/authorization/dynamic-data-source/SitesAdminDynamicAuthorizationDataSource.ts
+import { DynamicAuthorizationDataSourceName, SitesAdminDynamicAuthorizationDataSourceData } from '../../types/Authorization';
+
+import Constants from '../../utils/Constants';
+import DynamicAuthorizationDataSource from '../DynamicAuthorizationDataSource';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
+import UserStorage from '../../storage/mongodb/UserStorage';
+import _ from 'lodash';
+
+export default class SitesAdminDynamicAuthorizationDataSource
+ extends DynamicAuthorizationDataSource<SitesAdminDynamicAuthorizationDataSourceData> {
+
+ public getName(): DynamicAuthorizationDataSourceName {
+ return DynamicAuthorizationDataSourceName.SITES_ADMIN;
+ }
+
+ public async loadData(): Promise<void> {
+ const assignedSitesCompaniesData: SitesAdminDynamicAuthorizationDataSourceData = {};
+ // Get Site IDs from Site Admin flag
+ assignedSitesCompaniesData.siteIDs = await this.getSitesAdminSiteIDs();
+ // Set
+ this.setData(assignedSitesCompaniesData);
+ }
+
+ private async getSitesAdminSiteIDs(): Promise<string[]> {
+ // Get the Site IDs of the Sites for which the user is SiteAdmin
+ const sites = await UserStorage.getUserSites(this.tenant.id,
+ {
+ userID: this.userToken.id,
+ siteAdmin: true
+ }, Constants.DB_PARAMS_MAX_LIMIT,
+ ['siteID']
+ );
+ return sites.result.map((userSite) => userSite.siteID);
+ }
+}

ADD
src/authorization/dynamic-filters/SitesAdminDynamicAuthorizationFilter.ts
+import { AuthorizationFilter, DynamicAuthorizationDataSourceName, Entity } from '../../types/Authorization';
+
+import DynamicAuthorizationFilter from '../DynamicAuthorizationFilter';
+import SitesAdminDynamicAuthorizationDataSource from '../dynamic-data-source/SitesAdminDynamicAuthorizationDataSource';
+import Utils from '../../utils/Utils';
+
+export default class SitesAdminDynamicAuthorizationFilter extends DynamicAuthorizationFilter {
+ public processFilter(authorizationFilters: AuthorizationFilter, extraFilters: Record<string, any>): void {
+ // Get Site IDs
+ const sitesAdminDataSource = this.getDataSource(
+ DynamicAuthorizationDataSourceName.SITES_ADMIN) as SitesAdminDynamicAuthorizationDataSource;
+ const { siteIDs } = sitesAdminDataSource.getData();
+ // Check
+ if (!Utils.isEmptyArray(siteIDs)) {
+ // Force the filter
+ authorizationFilters.filters.siteIDs = siteIDs;
+ // Check if filter is provided
+ if (Utils.objectHasProperty(extraFilters, 'SiteID') &&
+ !Utils.isNullOrUndefined(extraFilters['SiteID'])) {
+ const filteredSiteIDs: string[] = extraFilters['SiteID'].split('|');
+ // Override
+ authorizationFilters.filters.siteIDs = filteredSiteIDs.filter(
+ (siteID) => authorizationFilters.filters.siteIDs.includes(siteID));
+ }
+ }
+ if (!Utils.isEmptyArray(authorizationFilters.filters.siteIDs)) {
+ authorizationFilters.authorized = true;
+ }
+ }
+
+ public getApplicableEntities(): Entity[] {
+ return [
+ Entity.SITE
+ ];
+ }
+
+ public getApplicableDataSources(): DynamicAuthorizationDataSourceName[] {
+ return [
+ DynamicAuthorizationDataSourceName.SITES_ADMIN
+ ];
+ }
+}

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
@@ -78,17 +78,19 @@ export default class AuthorizationService {
return authorizationFilters;
}
- public static async addSitesAuthorizations(tenant: Tenant, userToken: UserToken, sites: SiteDataResult, authorizationFilter: AuthorizationFilter): Promise<void> {
+ public static async addSitesAuthorizations(tenant: Tenant, userToken: UserToken, sites: SiteDataResult, authorizationFilter: AuthorizationFilter,
+ filteredRequest: Record<string, any>): Promise<void> {
// Add canCreate flag to root
sites.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.CREATE, authorizationFilter);
// Enrich
for (const site of sites.result) {
- await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter);
+ await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter, filteredRequest);
}
}
- public static async addSiteAuthorizations(tenant: Tenant, userToken: UserToken, site: Site, authorizationFilter: AuthorizationFilter): Promise<void> {
+ public static async addSiteAuthorizations(tenant: Tenant, userToken: UserToken, site: Site, authorizationFilter: AuthorizationFilter,
+ filteredRequest: Record<string, any>): Promise<void> {
// todo: remove when assign actions are in place
// Get Site Admins
const siteAdminIDs = await AuthorizationService.getSiteAdminSiteIDs(tenant.id, userToken);
@@ -99,9 +101,10 @@ export default class AuthorizationService {
site.canDelete = false;
} else {
const isSiteAdmin = siteAdminIDs.includes(site.id) || (userToken.role === UserRole.ADMIN);
- site.canRead = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.READ, authorizationFilter);
- site.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.DELETE, authorizationFilter);
- site.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANY, Action.UPDATE, authorizationFilter);
+ filteredRequest.SiteID = site.id;
+ site.canRead = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.READ, authorizationFilter, filteredRequest);
+ site.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.DELETE, authorizationFilter, filteredRequest);
+ site.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE, Action.UPDATE, authorizationFilter, filteredRequest);
// todo: change when assign actions are in place
site.canAssignUsers = await Authorizations.canAssignUsersSites(userToken);
site.canUnassignUsers = await Authorizations.canUnassignUsersSites(userToken) && isSiteAdmin;
@@ -871,7 +874,7 @@ export default class AuthorizationService {
return false;
}
// Check Dynamic Auth
- await AuthorizationService.processDynamicFilters(tenant, userToken, Action.LIST, Entity.COMPANIES,
+ await AuthorizationService.processDynamicFilters(tenant, userToken, action, entity,
authorizationFilters, authorizationContext, filteredRequest);
// Filter projected fields
authorizationFilters.projectFields = AuthorizationService.filterProjectFields(

MODIFY
src/server/rest/v1/service/SiteService.ts
src/server/rest/v1/service/SiteService.ts
@@ -321,7 +321,7 @@ export default class SiteService {
authorizationSitesFilter.projectFields
);
// Add Auth flags
- await AuthorizationService.addSitesAuthorizations(req.tenant, req.user, sites as SiteDataResult, authorizationSitesFilter);
+ await AuthorizationService.addSitesAuthorizations(req.tenant, req.user, sites as SiteDataResult, authorizationSitesFilter, filteredRequest);
// Return
res.json(sites);
next();

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -252,7 +252,7 @@ export default class UtilsService {
});
}
// Add actions
- await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter);
+ await AuthorizationService.addSiteAuthorizations(tenant, userToken, site, authorizationFilter, { SiteID: siteID });
// Check
const authorized = AuthorizationService.canPerfomAction(site, authAction);
if (!authorized) {

MODIFY
src/types/Authorization.ts
src/types/Authorization.ts
@@ -183,11 +183,13 @@ export interface SiteAuthorizationActions extends AuthorizationActions {
export enum DynamicAuthorizationFilterName {
ASSIGNED_SITES_COMPANIES = 'AssignedSitesCompanies',
ASSIGNED_SITES = 'AssignedSites',
+ SITES_ADMIN = 'SitesAdmin',
}
export enum DynamicAuthorizationDataSourceName {
ASSIGNED_SITES_COMPANIES = 'AssignedSitesCompanies',
ASSIGNED_SITES = 'AssignedSites',
+ SITES_ADMIN = 'SitesAdmin',
}
export interface DynamicAuthorizationDataSourceData {}
@@ -199,3 +201,7 @@ export interface AssignedSitesCompaniesDynamicAuthorizationDataSourceData extend
export interface AssignedSitesDynamicAuthorizationDataSourceData extends DynamicAuthorizationDataSourceData {
siteIDs?: string[];
}
+
+export interface SitesAdminDynamicAuthorizationDataSourceData extends DynamicAuthorizationDataSourceData {
+ siteIDs?: string[];
+}

Change handleUpdateSite logic