Refactor LIST USERS auth
MODIFY
src/authorization/Authorizations.ts
src/authorization/Authorizations.ts
@@ -315,8 +315,8 @@ export default class Authorizations {
return Authorizations.can(loggedUser, Entity.USERS_SITES, Action.LIST, authContext);
}
- public static async canListUsers(loggedUser: UserToken): Promise<boolean> {
- return Authorizations.canPerformAction(loggedUser, Entity.USERS, Action.LIST);
+ public static async canListUsers(loggedUser: UserToken, authContext?: AuthorizationContext): Promise<AuthorizationResult> {
+ return Authorizations.can(loggedUser, Entity.USERS, Action.LIST, authContext);
}
public static async canListUsersInErrors(loggedUser: UserToken): Promise<boolean> {

MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -7,7 +7,13 @@ import Constants from '../utils/Constants';
const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
superAdmin: {
grants: [
- { resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
+ {
+ resource: Entity.USERS, action: Action.LIST, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy',
+ 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale',
+ 'billingData.customerID', 'billingData.lastChangedOn'
+ ]
+ },
{ resource: Entity.USER, action: [Action.CREATE, Action.UPDATE], attributes: ['*'] },
{
resource: Entity.USER, action: Action.DELETE, attributes: ['*'],
@@ -30,7 +36,14 @@ 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.USERS, action: Action.LIST, attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy',
+ 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale',
+ 'billingData.customerID', 'billingData.lastChangedOn'
+ ]
+ },
+ { resource: Entity.USERS, action: [Action.SYNCHRONIZE_BILLING_USERS, Action.EXPORT, Action.IN_ERROR, Action.IMPORT], attributes: ['*'] },
{ resource: Entity.USER, action: [Action.CREATE, Action.UPDATE, Action.SYNCHRONIZE_BILLING_USER], attributes: ['*'] },
{
resource: Entity.USER, action: Action.DELETE, attributes: ['*'],
@@ -48,7 +61,13 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName'
]
},
- { resource: Entity.TAGS, action: [Action.LIST, Action.IMPORT, Action.EXPORT], attributes: ['*'] },
+ {
+ resource: Entity.TAGS, action: Action.LIST, attributes: [
+ 'id', 'userID', 'active', 'ocpiToken', 'description', 'issuer', 'default',
+ 'createdOn', 'lastChangedOn'
+ ]
+ },
+ { resource: Entity.TAGS, action: [Action.IMPORT, Action.EXPORT], attributes: ['*'] },
{ resource: Entity.TAG, action: [Action.CREATE, Action.UPDATE, Action.DELETE, Action.READ], attributes: ['*'] },
{ resource: Entity.CHARGING_PROFILES, action: Action.LIST, attributes: ['*'] },
{ resource: Entity.CHARGING_PROFILE, action: [Action.READ], attributes: ['*'] },
@@ -305,7 +324,16 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
}
},
{ resource: Entity.TAG, action: Action.READ, attributes: ['*'] },
- { resource: Entity.TAGS, action: Action.LIST, attributes: ['*'] },
+ {
+ resource: Entity.TAGS, action: Action.LIST, attributes: [
+ 'id', 'userID', 'active', 'ocpiToken', 'description', 'issuer', 'default',
+ 'createdOn', 'lastChangedOn'
+ ],
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['SitesAdmin'] }
+ }
+ },
{
resource: Entity.CHARGING_STATION,
action: [Action.REMOTE_STOP_TRANSACTION, Action.STOP_TRANSACTION],
@@ -448,7 +476,18 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
'basic': {}
},
grants: [
- { resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
+ {
+ resource: Entity.USERS, action: Action.LIST,
+ attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy',
+ 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale',
+ 'billingData.customerID', 'billingData.lastChangedOn'
+ ],
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['SitesAdmin'] }
+ },
+ },
{
resource: Entity.USER, action: [Action.READ], attributes: [
'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',
@@ -523,7 +562,18 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
'basic': {}
},
grants: [
- { resource: Entity.USERS, action: Action.LIST, attributes: ['*'] },
+ {
+ resource: Entity.USERS, action: Action.LIST,
+ attributes: [
+ 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy',
+ 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale',
+ 'billingData.customerID', 'billingData.lastChangedOn'
+ ],
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['SitesAdmin'] }
+ },
+ },
{
resource: Entity.USER, action: Action.READ, attributes: [
'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'locale', 'plateID',

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
@@ -338,23 +338,16 @@ export default class AuthorizationService {
}
public static async checkAndGetUsersAuthorizationFilters(tenant: Tenant, userToken: UserToken,
- filteredRequest: HttpUsersRequest): Promise<AuthorizationFilter> {
+ filteredRequest?: HttpUsersRequest): Promise<AuthorizationFilter> {
const authorizationFilters: AuthorizationFilter = {
filters: {},
dataSources: new Map(),
- projectFields: [
- 'id', 'name', 'firstName', 'email', 'role', 'status', 'issuer', 'createdOn', 'createdBy',
- 'lastChangedOn', 'lastChangedBy', 'eulaAcceptedOn', 'eulaAcceptedVersion', 'locale',
- 'billingData.customerID', 'billingData.lastChangedOn'
- ],
- authorized: userToken.role === UserRole.ADMIN || userToken.role === UserRole.SUPER_ADMIN,
+ projectFields: [],
+ authorized: false
};
- // Filter projected fields
- authorizationFilters.projectFields = AuthorizationService.filterProjectFields(
- authorizationFilters.projectFields, filteredRequest.ProjectFields);
- // Handle Sites
- await AuthorizationService.checkAssignedSiteAdminsAndOwners(
- tenant, userToken, filteredRequest, authorizationFilters);
+ // Check static & dynamic authorization
+ await this.canPerformAuthorizationAction(
+ tenant, userToken, Entity.USERS, Action.LIST, authorizationFilters, filteredRequest);
return authorizationFilters;
}
@@ -407,22 +400,12 @@ export default class AuthorizationService {
const authorizationFilters: AuthorizationFilter = {
filters: {},
dataSources: new Map(),
- projectFields: [
- 'id', 'userID', 'active', 'ocpiToken', 'description', 'issuer', 'default',
- 'createdOn', 'lastChangedOn'
- ],
- authorized: userToken.role === UserRole.ADMIN || userToken.role === UserRole.SUPER_ADMIN,
+ projectFields: [],
+ authorized: false
};
- if (await Authorizations.canListUsers(userToken)) {
- authorizationFilters.projectFields.push('userID', 'user.id', 'user.name', 'user.firstName', 'user.email',
- 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName');
- }
- // Filter projected fields
- authorizationFilters.projectFields = AuthorizationService.filterProjectFields(
- authorizationFilters.projectFields, filteredRequest.ProjectFields);
- // Handle Sites
- await AuthorizationService.checkAssignedSiteAdminsAndOwners(
- tenant, userToken, null, authorizationFilters);
+ // Check static & dynamic authorization
+ await this.canPerformAuthorizationAction(tenant, userToken, Entity.TAGS, Action.LIST,
+ authorizationFilters, filteredRequest);
return authorizationFilters;
}
@@ -452,8 +435,8 @@ export default class AuthorizationService {
authorized: false,
};
// Check static & dynamic authorization
- await this.canPerformAuthorizationAction(
- tenant, userToken, Entity.COMPANIES, Action.LIST, authorizationFilters, filteredRequest);
+ await this.canPerformAuthorizationAction(tenant, userToken, Entity.COMPANIES, Action.LIST,
+ authorizationFilters, filteredRequest);
return authorizationFilters;
}

MODIFY
src/server/rest/v1/service/TagService.ts
src/server/rest/v1/service/TagService.ts
@@ -720,35 +720,41 @@ export default class TagService {
}
private static async getTags(req: Request): Promise<DataResult<Tag>> {
- // Check auth
- if (!await Authorizations.canListTags(req.user)) {
+ // Filter
+ const filteredRequest = TagSecurity.filterTagsRequest(req.query);
+ // Get authorization filters
+ const authorizationTagsFilters = await AuthorizationService.checkAndGetTagsAuthorizationFilters(
+ req.tenant, req.user, filteredRequest);
+ if (!authorizationTagsFilters.authorized) {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: req.user,
action: Action.LIST, entity: Entity.TAGS,
- module: MODULE_NAME, method: 'handleGetTags'
+ module: MODULE_NAME, method: 'getTags'
});
}
- // // Check auth
- // if (!await Authorizations.canExportTags(req.user)) {
- // throw new AppAuthError({
- // errorCode: HTTPAuthError.FORBIDDEN,
- // user: req.user,
- // action: Action.LIST, entity: Entity.TAGS,
- // module: MODULE_NAME, method: 'handleGetTags'
- // });
+ // Get authorization filters
+ const authorizationUsersFilters = await AuthorizationService.checkAndGetUsersAuthorizationFilters(
+ req.tenant, req.user);
+ if (authorizationUsersFilters.authorized) {
+ authorizationTagsFilters.projectFields.push('userID', 'user.id', 'user.name', 'user.firstName', 'user.email',
+ 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName');
+ }
+ // todo: refactor
+ // if (await Authorizations.canListUsers(userToken)) {
+ // authorizationFilters.projectFields.push('userID', 'user.id', 'user.name', 'user.firstName', 'user.email',
+ // 'createdBy.name', 'createdBy.firstName', 'lastChangedBy.name', 'lastChangedBy.firstName');
// }
- // Filter
- const filteredRequest = TagSecurity.filterTagsRequest(req.query);
+ // todo: dynamic filters
+ // // Handle Sites
+ // await AuthorizationService.checkAssignedSiteAdminsAndOwners(
+ // tenant, userToken, null, authorizationFilters);
let userID: string;
if (Authorizations.isBasic(req.user)) {
userID = req.user.id;
} else {
userID = filteredRequest.UserID;
}
- // Get authorization filters
- const authorizationTagsFilters = await AuthorizationService.checkAndGetTagsAuthorizationFilters(
- req.tenant, req.user, filteredRequest);
// Get the tags
const tags = await TagStorage.getTags(req.user.tenantID,
{
@@ -758,7 +764,12 @@ export default class TagService {
active: filteredRequest.Active,
withUser: filteredRequest.WithUser,
},
- { limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.SortFields, onlyRecordCount: filteredRequest.OnlyRecordCount },
+ {
+ limit: filteredRequest.Limit,
+ skip: filteredRequest.Skip,
+ sort: filteredRequest.SortFields,
+ onlyRecordCount: filteredRequest.OnlyRecordCount
+ },
authorizationTagsFilters.projectFields,
);
// Return

Refactor LIST USERS auth