Change handleGetUsers (for a Site) logic
MODIFY
src/authorization/Authorizations.ts
src/authorization/Authorizations.ts
@@ -311,8 +311,8 @@ export default class Authorizations {
return Authorizations.canPerformAction(loggedUser, Entity.USERS_SITES, Action.UNASSIGN);
}
- public static async canListUsersSites(loggedUser: UserToken): Promise<boolean> {
- return Authorizations.canPerformAction(loggedUser, Entity.USERS_SITES, Action.LIST);
+ public static async canListUsersSites(loggedUser: UserToken, authContext?: AuthorizationContext): Promise<AuthorizationResult> {
+ return Authorizations.can(loggedUser, Entity.USERS_SITES, Action.LIST, authContext);
}
public static async canListUsers(loggedUser: UserToken): Promise<boolean> {

MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -108,7 +108,7 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
{ resource: Entity.USERS_CARS, action: Action.LIST, attributes: ['*'] },
{ resource: Entity.USERS_CARS, action: Action.ASSIGN, attributes: ['*'] },
{ resource: Entity.NOTIFICATION, action: Action.CREATE, attributes: ['*'] },
- { resource: Entity.USERS_SITES, action: Action.LIST, attributes: ['*'] },
+ { resource: Entity.USERS_SITES, action: Action.LIST, attributes: ['user.id', 'user.name', 'user.firstName', 'user.email', 'user.role', 'siteAdmin', 'siteOwner', 'siteID'] },
{ resource: Entity.USERS_SITES, action: [Action.ASSIGN, Action.UNASSIGN], attributes: ['*'] },
{ resource: Entity.PAYMENT_METHODS, action: Action.LIST, attributes: ['*'] },
{
@@ -311,8 +311,21 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
grants: [
{ resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
{ resource: Entity.USER, action: [Action.READ], attributes: ['*'] },
- { resource: Entity.USERS_SITES, action: Action.LIST, attributes: ['*'] },
- { resource: Entity.USERS_SITES, action: [Action.UNASSIGN], attributes: ['*'] },
+ {
+ resource: Entity.USERS_SITES, action: Action.LIST,
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['SitesAdmin'] }
+ },
+ attributes: ['user.id', 'user.name', 'user.firstName', 'user.email', 'user.role', 'siteAdmin', 'siteOwner', 'siteID']
+ },
+ { resource: Entity.USERS_SITES, action: Action.UNASSIGN,
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['SitesAdmin'] }
+ },
+ attributes: ['*']
+ },
{ resource: Entity.SITE, action: [Action.UPDATE],
condition: {
Fn: 'custom:dynamicAuthorizationFilters',

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
@@ -125,22 +125,33 @@ export default class AuthorizationService {
return authorizationFilters;
}
- public static async checkAndGetSiteUsersAuthorizationFilters(
- tenant: Tenant, userToken: UserToken, filteredRequest: HttpSiteUsersRequest): Promise<AuthorizationFilter> {
+ public static async checkAndGetSiteUsersAuthorizationFilters(tenant: Tenant, userToken: UserToken,
+ filteredRequest: Record<string, any>): Promise<AuthorizationFilter> {
const authorizationFilters: AuthorizationFilter = {
filters: {},
dataSources: new Map(),
- projectFields: [
- 'user.id', 'user.name', 'user.firstName', 'user.email', 'user.role', 'siteAdmin', 'siteOwner', 'siteID'
- ],
- authorized: userToken.role === UserRole.ADMIN,
+ projectFields: [ ],
+ authorized: false,
};
+ // Check static auth
+ const authorizationContext: AuthorizationContext = {};
+ const authResult = await Authorizations.canListUsersSites(userToken, authorizationContext);
+ authorizationFilters.authorized = authResult.authorized;
+ // Check
+ if (!authorizationFilters.authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: userToken,
+ action: Action.READ, entity: Entity.USERS_SITES,
+ module: MODULE_NAME, method: 'checkAndGetSiteUsersAuthorizationFilters',
+ });
+ }
+ // Process dynamic filters
+ await AuthorizationService.processDynamicFilters(tenant, userToken, Action.READ, Entity.USERS_SITES,
+ authorizationFilters, authorizationContext, { SiteID: filteredRequest.SiteID });
// Filter projected fields
authorizationFilters.projectFields = AuthorizationService.filterProjectFields(
- authorizationFilters.projectFields, filteredRequest.ProjectFields);
- // Handle Sites
- await AuthorizationService.checkAssignedSiteAdminsAndOwners(
- tenant, userToken, filteredRequest, authorizationFilters);
+ authResult.fields, filteredRequest.ProjectFields);
return authorizationFilters;
}

MODIFY
src/server/rest/v1/service/SiteService.ts
src/server/rest/v1/service/SiteService.ts
@@ -195,30 +195,21 @@ export default class SiteService {
// Check if component is active
UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.ORGANIZATION,
Action.UPDATE, Entity.SITE, MODULE_NAME, 'handleGetUsers');
- // Check auth
- if (!await Authorizations.canListUsersSites(req.user)) {
- throw new AppAuthError({
- errorCode: HTTPAuthError.FORBIDDEN,
- user: req.user,
- action: Action.LIST, entity: Entity.USERS_SITES,
- module: MODULE_NAME, method: 'handleGetUsers'
- });
- }
// Filter
const filteredRequest = SiteSecurity.filterSiteUsersRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.SiteID, MODULE_NAME, 'handleGetUsers', req.user);
- // Check Site
+ // Check Site - is this needed? it works without.
try {
await UtilsService.checkAndGetSiteAuthorization(
- req.tenant, req.user, filteredRequest.SiteID, Action.READ, action, {});
+ req.tenant, req.user, filteredRequest.SiteID, Action.READ, action, {}, true);
} catch (error) {
UtilsService.sendEmptyDataResult(res, next);
return;
}
- // Check auth
- const authorizationSiteUsersFilters = await AuthorizationService.checkAndGetSiteUsersAuthorizationFilters(
+ // Check dynamic auth for reading Users
+ const authorizationSiteUsersFilter = await AuthorizationService.checkAndGetSiteUsersAuthorizationFilters(
req.tenant, req.user, filteredRequest);
- if (!authorizationSiteUsersFilters.authorized) {
+ if (!authorizationSiteUsersFilter.authorized) {
UtilsService.sendEmptyDataResult(res, next);
return;
}
@@ -227,7 +218,7 @@ export default class SiteService {
{
search: filteredRequest.Search,
siteIDs: [ filteredRequest.SiteID ],
- ...authorizationSiteUsersFilters.filters
+ ...authorizationSiteUsersFilter.filters
},
{
limit: filteredRequest.Limit,
@@ -235,7 +226,7 @@ export default class SiteService {
sort: filteredRequest.SortFields,
onlyRecordCount: filteredRequest.OnlyRecordCount
},
- authorizationSiteUsersFilters.projectFields
+ authorizationSiteUsersFilter.projectFields
);
res.json(users);
next();

Change handleGetUsers (for a Site) logic