Add authorizations for each tag. Refactor handleDeleteTag.
MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -347,6 +347,13 @@ const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
args: { filters: ['OwnUser', 'SiteAdminUsers'] }
}
},
+ {
+ resource: Entity.TAG, action: Action.DELETE, attributes: ['*'],
+ condition: {
+ Fn: 'custom:dynamicAuthorizationFilters',
+ args: { filters: ['OwnUser', 'SiteAdminUsers'] }
+ }
+ },
{
resource: Entity.CHARGING_STATION,
action: [Action.REMOTE_STOP_TRANSACTION, Action.STOP_TRANSACTION],

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
import { Action, AuthorizationActions, AuthorizationContext, AuthorizationFilter, Entity, SiteAreaAuthorizationActions } from '../../../../types/Authorization';
-import { CompanyDataResult, SiteAreaDataResult, SiteDataResult } from '../../../../types/DataResult';
+import { CompanyDataResult, SiteAreaDataResult, SiteDataResult, TagDataResult } from '../../../../types/DataResult';
import { HttpAssignAssetsToSiteAreaRequest, HttpSiteAreaRequest, HttpSiteAreasRequest } from '../../../../types/requests/HttpSiteAreaRequest';
import { HttpChargingStationRequest, HttpChargingStationsRequest } from '../../../../types/requests/HttpChargingStationRequest';
import { HttpCompaniesRequest, HttpCompanyRequest } from '../../../../types/requests/HttpCompanyRequest';
@@ -22,6 +22,7 @@ import Site from '../../../../types/Site';
import SiteArea from '../../../../types/SiteArea';
import SiteAreaStorage from '../../../../storage/mongodb/SiteAreaStorage';
import SiteStorage from '../../../../storage/mongodb/SiteStorage';
+import Tag from '../../../../types/Tag';
import Tenant from '../../../../types/Tenant';
import TenantComponents from '../../../../types/TenantComponents';
import UserStorage from '../../../../storage/mongodb/UserStorage';
@@ -422,6 +423,29 @@ export default class AuthorizationService {
return authorizationFilters;
}
+ public static async addTagsAuthorizations(tenant: Tenant, userToken: UserToken, tags: TagDataResult,
+ authorizationFilter: AuthorizationFilter, filteredRequest: HttpTagsRequest): Promise<void> {
+ // // Add canCreate flag to root
+ // tags.canCreate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.CREATE, authorizationFilter);
+ // Enrich
+ for (const tag of tags.result) {
+ await AuthorizationService.addTagAuthorizations(tenant, userToken, tag, authorizationFilter);
+ }
+ }
+
+ public static async addTagAuthorizations(tenant: Tenant, userToken: UserToken, tag: Tag, authorizationFilter: AuthorizationFilter): Promise<void> {
+ // Enrich
+ if (!tag.issuer) {
+ tag.canRead = true;
+ // tag.canUpdate = false;
+ tag.canDelete = false;
+ } else {
+ tag.canRead = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.READ, authorizationFilter);
+ tag.canDelete = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.DELETE, authorizationFilter);
+ // tag.canUpdate = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.TAG, Action.UPDATE, authorizationFilter);
+ }
+ }
+
public static async checkAndGetCompaniesAuthorizationFilters(tenant: Tenant, userToken: UserToken,
filteredRequest: HttpCompaniesRequest): Promise<AuthorizationFilter> {
const authorizationFilters: AuthorizationFilter = {

MODIFY
src/server/rest/v1/service/TagService.ts
src/server/rest/v1/service/TagService.ts
import { Action, Entity } from '../../../../types/Authorization';
import { ActionsResponse, ImportStatus } from '../../../../types/GlobalType';
import { AsyncTaskType, AsyncTasks } from '../../../../types/AsyncTask';
+import { DataResult, TagDataResult } from '../../../../types/DataResult';
import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError';
import { NextFunction, Request, Response } from 'express';
import Tag, { ImportedTag, TagRequiredImportProperties } from '../../../../types/Tag';
@@ -13,7 +14,6 @@ import Authorizations from '../../../../authorization/Authorizations';
import Busboy from 'busboy';
import CSVError from 'csvtojson/v2/CSVError';
import Constants from '../../../../utils/Constants';
-import { DataResult } from '../../../../types/DataResult';
import EmspOCPIClient from '../../../../client/ocpi/EmspOCPIClient';
import JSONStream from 'JSONStream';
import LockingHelper from '../../../../locking/LockingHelper';
@@ -80,19 +80,12 @@ export default class TagService {
public static async handleDeleteTag(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Filter
const filteredRequest = TagSecurity.filterTagRequestByID(req.query);
- UtilsService.assertIdIsProvided(action, filteredRequest.ID, MODULE_NAME, 'handleDeleteTag', req.user);
- // Check auth
- if (!await Authorizations.canDeleteTag(req.user)) {
- throw new AppAuthError({
- errorCode: HTTPAuthError.FORBIDDEN,
- user: req.user,
- action: Action.DELETE, entity: Entity.TAG,
- module: MODULE_NAME, method: 'handleDeleteTag',
- value: filteredRequest.ID
- });
- }
+ // Check and Get Tag
+ const tag = await UtilsService.checkAndGetTagAuthorization(req.tenant, req.user, filteredRequest.ID, Action.DELETE, action,
+ { withUser: true }, true);
// Delete
- await TagService.deleteTags(action, req.user, [filteredRequest.ID]);
+ await TagService.deleteTags(action, req.user, [tag.id]);
+ // Return
res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -737,6 +730,9 @@ export default class TagService {
},
authorizationTagsFilters.projectFields,
);
+ // Add Auth flags
+ await AuthorizationService.addTagsAuthorizations(req.tenant, req.user, tags as TagDataResult,
+ authorizationUsersFilters, filteredRequest);
// Return
return tags;
}

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -545,6 +545,19 @@ export default class UtilsService {
delete tag.userID;
delete tag.user;
}
+ // Add actions
+ await AuthorizationService.addTagAuthorizations(tenant, userToken, tag, authorizationFilter);
+ // Check
+ const authorized = AuthorizationService.canPerformAction(tag, authAction);
+ if (!authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: userToken,
+ action: authAction, entity: Entity.TAG,
+ module: MODULE_NAME, method: 'checkAndGetTagAuthorization',
+ value: tagID
+ });
+ }
return tag;
}

MODIFY
src/types/DataResult.ts
src/types/DataResult.ts
import Company from './Company';
import Site from './Site';
import SiteArea from './SiteArea';
+import Tag from './Tag';
import { Transaction } from '@google-cloud/firestore';
export interface DataResult<T> {
@@ -21,6 +22,10 @@ export interface SiteAreaDataResult extends DataResult<SiteArea>{
canCreate: boolean;
}
+export interface TagDataResult extends DataResult<Tag>{
+ canCreate: boolean;
+}
+
export interface TransactionDataResult {
count: number;
result: Transaction[];

MODIFY
src/types/Tag.ts
src/types/Tag.ts
+import { AuthorizationActions } from './Authorization';
import CreatedUpdatedProps from './CreatedUpdatedProps';
import { ImportStatus } from './GlobalType';
import { OCPIToken } from './ocpi/OCPIToken';
import User from './User';
-export default interface Tag extends CreatedUpdatedProps {
+export default interface Tag extends CreatedUpdatedProps, AuthorizationActions {
id: string;
description?: string;
issuer: boolean;

Add authorizations for each tag. Refactor handleDeleteTag.