Change logic for handleUpdateSiteUserAdmin & handleUpdateSiteOwner
MODIFY
src/authorization/Authorizations.ts
src/authorization/Authorizations.ts
@@ -347,9 +347,8 @@ export default class Authorizations {
return Authorizations.canPerformAction(loggedUser, Entity.TAGS, Action.IMPORT);
}
- public static async canReadUser(loggedUser: UserToken, userID: string): Promise<boolean> {
- return Authorizations.canPerformAction(loggedUser, Entity.USER, Action.READ,
- { user: userID, owner: loggedUser.id });
+ public static async canReadUser(loggedUser: UserToken, authContext?: AuthorizationContext): Promise<AuthorizationResult> {
+ return Authorizations.can(loggedUser, Entity.USER, Action.READ, authContext);
}
public static async canCreateUser(loggedUser: UserToken): Promise<boolean> {

MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -8,11 +8,17 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
superAdmin: {
grants: [
{ resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
- { resource: Entity.USER, action: [Action.CREATE, Action.READ, Action.UPDATE], attributes: ['*'] },
+ { resource: Entity.USER, action: [Action.CREATE, Action.UPDATE], attributes: ['*'] },
{
resource: Entity.USER, action: Action.DELETE, attributes: ['*'],
condition: { Fn: 'NOT_EQUALS', args: { 'user': '$.owner' } }
},
+ {
+ resource: Entity.USER, action: Action.READ, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
+ 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
+ ]
+ },
{ resource: Entity.LOGGINGS, action: Action.LIST, attributes: ['*'] },
{ resource: Entity.LOGGING, action: Action.READ, attributes: ['*'] },
{ resource: Entity.TENANTS, action: Action.LIST, attributes: ['*'] },
@@ -25,11 +31,17 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
admin: {
grants: [
{ resource: Entity.USERS, action: [Action.LIST, Action.SYNCHRONIZE_BILLING_USERS, Action.EXPORT, Action.IN_ERROR, Action.IMPORT], attributes: ['*'] },
- { resource: Entity.USER, action: [Action.CREATE, Action.READ, Action.UPDATE, Action.SYNCHRONIZE_BILLING_USER], attributes: ['*'] },
+ { resource: Entity.USER, action: [Action.CREATE, Action.UPDATE, Action.SYNCHRONIZE_BILLING_USER], attributes: ['*'] },
{
resource: Entity.USER, action: Action.DELETE, attributes: ['*'],
condition: { Fn: 'NOT_EQUALS', args: { 'user': '$.owner' } },
},
+ {
+ resource: Entity.USER, action: Action.READ, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
+ 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
+ ]
+ },
{ resource: Entity.COMPANIES, action: Action.LIST, attributes: [
'id', 'name', 'address', 'logo', 'issuer', 'distanceMeters', 'createdOn', 'lastChangedOn',
'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName'
@@ -121,7 +133,14 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
basic: {
grants: [
{
- resource: Entity.USER, action: [Action.READ, Action.UPDATE], attributes: ['*'],
+ resource: Entity.USER, action: Action.READ, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
+ 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
+ ],
+ condition: { Fn: 'EQUALS', args: { 'user': '$.owner' } }
+ },
+ {
+ resource: Entity.USER, action: Action.UPDATE, attributes: ['*'],
condition: { Fn: 'EQUALS', args: { 'user': '$.owner' } }
},
{ resource: Entity.SETTING, action: Action.READ, attributes: ['*'] },
@@ -310,7 +329,12 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
grants: [
{ resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
- { resource: Entity.USER, action: [Action.READ], attributes: ['*'] },
+ {
+ resource: Entity.USER, action: [Action.READ], attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
+ 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
+ ]
+ },
{
resource: Entity.USERS_SITES, action: Action.LIST,
condition: {
@@ -371,7 +395,12 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
grants: [
{ resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
- { resource: Entity.USER, action: [Action.READ], attributes: ['*'] },
+ {
+ resource: Entity.USER, action: Action.READ, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
+ 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
+ ]
+ },
{
resource: Entity.TRANSACTION, action: [Action.READ, Action.REFUND_TRANSACTION], attributes: ['*'],
condition: { Fn: 'LIST_CONTAINS', args: { 'sitesOwner': '$.site' } }

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
@@ -353,18 +353,24 @@ export default class AuthorizationService {
return authorizationFilters;
}
- public static async addUsersAuthorizations(tenant: Tenant, userToken: UserToken, users: User[]): Promise<void> {
+ public static async addUsersAuthorizations(tenant: Tenant, userToken: UserToken, users: User[], authorizationFilter: AuthorizationFilter): Promise<void> {
// Enrich
for (const user of users) {
- await AuthorizationService.addUserAuthorizations(tenant, userToken, user);
+ await AuthorizationService.addUserAuthorizations(tenant, userToken, user, authorizationFilter);
}
}
- public static async addUserAuthorizations(tenant: Tenant, userToken: UserToken, user: User): Promise<void> {
+ public static async addUserAuthorizations(tenant: Tenant, userToken: UserToken, user: User, authorizationFilter: AuthorizationFilter): Promise<void> {
// Enrich
- user.canRead = await Authorizations.canReadUser(userToken, user.id);
- user.canUpdate = await Authorizations.canUpdateUser(userToken, user.id);
- user.canDelete = await Authorizations.canDeleteUser(userToken, user.id);
+ if (!user.issuer) {
+ user.canRead = true;
+ user.canUpdate = false;
+ user.canDelete = false;
+ } else {
+ user.canRead = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.READ, authorizationFilter);
+ user.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.DELETE, authorizationFilter);
+ user.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER, Action.UPDATE, authorizationFilter);
+ }
}
public static async checkAndGetUsersAuthorizationFilters(
@@ -413,18 +419,28 @@ export default class AuthorizationService {
const authorizationFilters: AuthorizationFilter = {
filters: {},
dataSources: new Map(),
- projectFields: [
- 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
- 'notificationsActive', 'notifications', 'phone', 'mobile', 'iNumber', 'costCenter', 'address'
- ],
- authorized: userToken.role === UserRole.ADMIN || userToken.role === UserRole.SUPER_ADMIN,
+ projectFields: [],
+ authorized: false,
};
+ // Check static auth
+ const authorizationContext: AuthorizationContext = {};
+ const authResult = await Authorizations.canReadUser(userToken, authorizationContext);
+ authorizationFilters.authorized = authResult.authorized;
+ // Check
+ if (!authorizationFilters.authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: userToken,
+ action: Action.READ, entity: Entity.USER,
+ module: MODULE_NAME, method: 'checkAndGetUserAuthorizationFilters',
+ });
+ }
+ // Process dynamic filters
+ await AuthorizationService.processDynamicFilters(tenant, userToken, Action.READ, Entity.USER,
+ authorizationFilters, authorizationContext, { UserID: filteredRequest.ID });
// Filter projected fields
authorizationFilters.projectFields = AuthorizationService.filterProjectFields(
- authorizationFilters.projectFields, filteredRequest.ProjectFields);
- // Handle Sites
- await AuthorizationService.checkAssignedSiteAdminsAndOwners(
- tenant, userToken, null, authorizationFilters);
+ authResult.fields, filteredRequest.ProjectFields);
return authorizationFilters;
}

MODIFY
src/server/rest/v1/service/CarService.ts
src/server/rest/v1/service/CarService.ts
@@ -468,7 +468,7 @@ export default class CarService {
UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetCar', req.user);
// Check User
let userProject: string[] = [];
- if (await Authorizations.canReadUser(req.user, req.user.id)) {
+ if (await Authorizations.canReadUser(req.user)) {
userProject = [ 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName', 'carUsers.id',
'carUsers.user.id', 'carUsers.user.name', 'carUsers.user.firstName', 'carUsers.user.email', 'carUsers.default', 'carUsers.owner'
];
@@ -617,7 +617,7 @@ export default class CarService {
UtilsService.assertObjectExists(action, foundUser, `User ID '${userToCheck.user.id}' does not exist`,
MODULE_NAME, 'handleAssignCarUsers', loggedUser);
// Auth
- if (!await Authorizations.canReadUser(loggedUser, foundUser.id)) {
+ if (!await Authorizations.canReadUser(loggedUser)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: loggedUser,

MODIFY
src/server/rest/v1/service/TagService.ts
src/server/rest/v1/service/TagService.ts
@@ -62,7 +62,7 @@ export default class TagService {
UtilsService.assertObjectExists(action, tag, `Tag ID '${filteredRequest.ID}' does not exist`,
MODULE_NAME, 'handleGetTag', req.user);
// Check Users
- if (!await Authorizations.canReadUser(req.user, tag.userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
delete tag.userID;
delete tag.user;
}

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -15,7 +15,6 @@ import Consumption from '../../../../types/Consumption';
import ConsumptionStorage from '../../../../storage/mongodb/ConsumptionStorage';
import Cypher from '../../../../utils/Cypher';
import { DataResult } from '../../../../types/DataResult';
-import I18nManager from '../../../../utils/I18nManager';
import LockingHelper from '../../../../locking/LockingHelper';
import LockingManager from '../../../../locking/LockingManager';
import Logging from '../../../../utils/Logging';
@@ -576,7 +575,7 @@ export default class TransactionService {
});
}
// Check User
- if (!await Authorizations.canReadUser(req.user, transaction.userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
// Remove User
delete transaction.user;
delete transaction.userID;
@@ -655,7 +654,7 @@ export default class TransactionService {
});
}
// Check User
- if (!await Authorizations.canReadUser(req.user, transaction.userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
// Remove User
delete transaction.user;
delete transaction.userID;

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -73,7 +73,7 @@ export default class UserService {
const userID = UserSecurity.filterDefaultTagCarRequestByUserID(req.query);
UtilsService.assertIdIsProvided(action, userID, MODULE_NAME, 'handleGetUserDefaultTagCar', req.user);
// Check auth
- if (!await Authorizations.canReadUser(req.user, userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -155,7 +155,7 @@ export default class UserService {
});
}
// Check auth
- if (!await Authorizations.canReadUser(req.user, filteredRequest.userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -593,7 +593,7 @@ export default class UserService {
const filteredRequest = UserSecurity.filterUserRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleGetUser', req.user);
// Check auth
- if (!await Authorizations.canReadUser(req.user, filteredRequest.ID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -624,7 +624,7 @@ export default class UserService {
const userID = UserSecurity.filterUserByIDRequest(req.query);
UtilsService.assertIdIsProvided(action, userID, MODULE_NAME, 'handleGetUserImage', req.user);
// Check auth
- if (!await Authorizations.canReadUser(req.user, userID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -672,7 +672,7 @@ export default class UserService {
const filteredRequest = UserSecurity.filterUserSitesRequest(req.query);
UtilsService.assertIdIsProvided(action, filteredRequest.UserID, MODULE_NAME, 'handleGetSites', req.user);
// Check auth
- if (!await Authorizations.canReadUser(req.user, filteredRequest.UserID)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -771,7 +771,7 @@ export default class UserService {
authorizationUserInErrorFilters.projectFields
);
// Add Auth flags
- await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users.result);
+ await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users.result, authorizationUserInErrorFilters);
// Return
res.json(users);
next();
@@ -1118,7 +1118,7 @@ export default class UserService {
});
}
// Check auth
- if (!await Authorizations.canReadUser(req.user, id)) {
+ if (!await Authorizations.canReadUser(req.user)) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
@@ -1335,7 +1335,7 @@ export default class UserService {
authorizationUsersFilters.projectFields
);
// Add Auth flags
- await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users.result);
+ await AuthorizationService.addUsersAuthorizations(req.tenant, req.user, users.result, authorizationUsersFilters);
// Return
return users;
}

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -153,18 +153,8 @@ export default class UtilsService {
public static async checkAndGetUserAuthorization(tenant: Tenant, userToken: UserToken, userID: string, authAction: Action,
action: ServerAction, additionalFilters: Record<string, any>, applyProjectFields = false): Promise<User> {
- // Check static auth for reading user
- if (!await Authorizations.canReadUser(userToken, userID)) {
- throw new AppAuthError({
- errorCode: HTTPAuthError.FORBIDDEN,
- user: userToken,
- action: Action.READ, entity: Entity.USER,
- module: MODULE_NAME, method: 'checkAndGetCompanyAuthorization',
- value: userID
- });
- }
// Check mandatory fields
- UtilsService.assertIdIsProvided(action, userID, MODULE_NAME, 'checkAndGetCompanyAuthorization', userToken);
+ UtilsService.assertIdIsProvided(action, userID, MODULE_NAME, 'checkAndGetUserAuthorization', userToken);
// Get dynamic auth
const authorizationFilter = await AuthorizationService.checkAndGetUserAuthorizationFilters(
tenant, userToken, { ID: userID });
@@ -173,7 +163,7 @@ export default class UtilsService {
errorCode: HTTPAuthError.FORBIDDEN,
user: userToken,
action: Action.READ, entity: Entity.USER,
- module: MODULE_NAME, method: 'checkAndGetCompanyAuthorization',
+ module: MODULE_NAME, method: 'checkAndGetUserAuthorization',
value: userID
});
}
@@ -186,20 +176,20 @@ export default class UtilsService {
applyProjectFields ? authorizationFilter.projectFields : null
);
UtilsService.assertObjectExists(action, user, `User ID '${userID}' does not exist`,
- MODULE_NAME, 'checkAndGetCompanyAuthorization', userToken);
+ MODULE_NAME, 'checkAndGetUserAuthorization', userToken);
// External User
if (!user.issuer) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
errorCode: HTTPError.GENERAL_ERROR,
message: `User '${user.name}' with ID '${user.id}' not issued by the organization`,
- module: MODULE_NAME, method: 'checkAndGetCompanyAuthorization',
+ module: MODULE_NAME, method: 'checkAndGetUserAuthorization',
user: userToken,
action: action
});
}
// Add actions
- await AuthorizationService.addUserAuthorizations(tenant, userToken, user);
+ await AuthorizationService.addUserAuthorizations(tenant, userToken, user, authorizationFilter);
// Check
const authorized = AuthorizationService.canPerfomAction(user, authAction);
if (!authorized) {
@@ -207,7 +197,7 @@ export default class UtilsService {
errorCode: HTTPAuthError.FORBIDDEN,
user: userToken,
action: authAction, entity: Entity.USER,
- module: MODULE_NAME, method: 'checkAndGetCompanyAuthorization',
+ module: MODULE_NAME, method: 'checkAndGetUserAuthorization',
value: userID
});
}

Change logic for handleUpdateSiteUserAdmin & handleUpdateSiteOwner