assign/unassign working
MODIFY
src/authorization/AuthorizationsDefinition.ts
src/authorization/AuthorizationsDefinition.ts
@@ -267,7 +267,7 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
},
{
- resource: Entity.USER_SITE, action: [Action.ASSIGN, Action.READ, Action.UPDATE, Action.LIST],
+ resource: Entity.USER_SITE, action: [Action.ASSIGN, Action.ASSIGN_SITES_TO_USER, Action.READ, Action.UPDATE, Action.LIST],
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {
@@ -286,12 +286,23 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
Fn: 'custom:dynamicAuthorizations',
args: {
asserts: [],
- filters: ['-OwnUser', 'LocalIssuer']
+ filters: ['LocalIssuer']
}
}
},
{
- resource: Entity.SITE_USER, action: [Action.ASSIGN, Action.READ, Action.UPDATE, Action.LIST],
+ resource: Entity.USER_SITE,
+ action: Action.UNASSIGN_SITES_FROM_USER,
+ condition: {
+ Fn: 'custom:dynamicAuthorizations',
+ args: {
+ asserts: [],
+ filters: ['-OwnUser', 'LocalIssuer']
+ }
+ },
+ },
+ {
+ resource: Entity.SITE_USER, action: [Action.ASSIGN, Action.ASSIGN_USERS_TO_SITE, Action.READ, Action.UPDATE, Action.LIST],
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {
@@ -306,13 +317,24 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
{
resource: Entity.SITE_USER,
action: Action.UNASSIGN,
- // condition: {
- // Fn: 'custom:dynamicAuthorizations',
- // args: {
- // asserts: [],
- // filters: ['-OwnUser', 'LocalIssuer']
- // }
- // }
+ condition: {
+ Fn: 'custom:dynamicAuthorizations',
+ args: {
+ asserts: [],
+ filters: ['LocalIssuer']
+ }
+ }
+ },
+ {
+ resource: Entity.SITE_USER,
+ action: Action.UNASSIGN_USERS_FROM_SITE,
+ condition: {
+ Fn: 'custom:dynamicAuthorizations',
+ args: {
+ asserts: [],
+ filters: ['-OwnUser', 'LocalIssuer']
+ }
+ },
},
{
resource: Entity.SITE_AREA, action: Action.LIST,
@@ -1220,7 +1242,7 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
}
},
{
- resource: Entity.USER_SITE, action: [Action.ASSIGN, Action.READ, Action.UPDATE, Action.LIST],
+ resource: Entity.USER_SITE, action: [Action.ASSIGN, Action.ASSIGN_SITES_TO_USER, Action.READ, Action.UPDATE, Action.LIST],
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {
@@ -1235,6 +1257,17 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
{
resource: Entity.USER_SITE,
action: Action.UNASSIGN,
+ condition: {
+ Fn: 'custom:dynamicAuthorizations',
+ args: {
+ asserts: [],
+ filters: ['SitesAdminOrOwner', 'LocalIssuer']
+ }
+ },
+ },
+ {
+ resource: Entity.USER_SITE,
+ action: Action.UNASSIGN_SITES_FROM_USER,
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {
@@ -1244,7 +1277,7 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
},
},
{
- resource: Entity.SITE_USER, action: [Action.ASSIGN, Action.READ, Action.UPDATE, Action.LIST],
+ resource: Entity.SITE_USER, action: [Action.ASSIGN, Action.ASSIGN_USERS_TO_SITE, Action.READ, Action.UPDATE, Action.LIST],
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {
@@ -1259,6 +1292,17 @@ export const AUTHORIZATION_DEFINITION: AuthorizationDefinition = {
{
resource: Entity.SITE_USER,
action: Action.UNASSIGN,
+ condition: {
+ Fn: 'custom:dynamicAuthorizations',
+ args: {
+ asserts: [],
+ filters: ['SitesAdminOrOwner', 'LocalIssuer']
+ }
+ },
+ },
+ {
+ resource: Entity.SITE_USER,
+ action: Action.UNASSIGN_USERS_FROM_SITE,
condition: {
Fn: 'custom:dynamicAuthorizations',
args: {

MODIFY
src/server/rest/v1/service/AuthorizationService.ts
src/server/rest/v1/service/AuthorizationService.ts
@@ -13,8 +13,9 @@ import { HttpSiteAssignUsersRequest, HttpSiteRequest, HttpSiteUsersRequest } fro
import { HttpTagRequest, HttpTagsRequest } from '../../../../types/requests/HttpTagRequest';
import { HttpUserAssignSitesRequest, HttpUserRequest, HttpUserSitesRequest, HttpUsersRequest } from '../../../../types/requests/HttpUserRequest';
import { OCPPProtocol, OCPPVersion } from '../../../../types/ocpp/OCPPServer';
+import Site, { UserSite } from '../../../../types/Site';
import Tenant, { TenantComponents } from '../../../../types/Tenant';
-import User, { UserRole } from '../../../../types/User';
+import User, { SiteUser, UserRole } from '../../../../types/User';
import AppAuthError from '../../../../exception/AppAuthError';
import Asset from '../../../../types/Asset';
@@ -31,7 +32,6 @@ import PricingDefinition from '../../../../types/Pricing';
import RegistrationToken from '../../../../types/RegistrationToken';
import { ServerAction } from '../../../../types/Server';
import { Setting } from '../../../../types/Setting';
-import Site from '../../../../types/Site';
import SiteArea from '../../../../types/SiteArea';
import Tag from '../../../../types/Tag';
import UserToken from '../../../../types/UserToken';
@@ -61,6 +61,30 @@ export default class AuthorizationService {
userSites.metadata = authorizationFilter.metadata;
// Add Authorizations
userSites.canUpdateUserSites = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.USER_SITE, Action.UPDATE, authorizationFilter);
+ for (const userSite of userSites.result) {
+ await AuthorizationService.addUserSiteAuthorizations(tenant, userToken, userSite, authorizationFilter);
+ }
+ }
+
+ public static async addUserSiteAuthorizations(tenant: Tenant, userToken: UserToken, userSite: UserSite, authorizationFilter: AuthorizationFilter): Promise<void> {
+ userSite.canAssignToUser = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.USER_SITE, Action.ASSIGN, authorizationFilter, { UserID: userSite.userID }, userSite);
+ userSite.canUnassignFromUser = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.USER_SITE, Action.UNASSIGN, authorizationFilter, { UserID: userSite.userID }, userSite);
+ // Optimize data over the net
+ Utils.removeCanPropertiesWithFalseValue(userSite);
+ }
+
+ // eslint-disable-next-line max-len
+ public static async addUserSiteAuthToSitesAuthorizations(tenant: Tenant, userToken: UserToken, user: User, sites: Site[], authorizationFilter: AuthorizationFilter): Promise<void> {
+ for (const site of sites) {
+ site.canAssignToUser = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.USER_SITE, Action.ASSIGN_SITES_TO_USER, authorizationFilter, { UserID: user.id }, site);
+ site.canUnassignFromUser = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.USER_SITE, Action.UNASSIGN_SITES_FROM_USER, authorizationFilter, { UserID: user.id }, site);
+ // Optimize data over the net
+ Utils.removeCanPropertiesWithFalseValue(site);
+ }
}
public static async addSiteUsersAuthorizations(tenant: Tenant, userToken: UserToken, siteUsers: SiteUserDataResult, authorizationFilter: AuthorizationFilter): Promise<void> {
@@ -68,6 +92,30 @@ export default class AuthorizationService {
siteUsers.metadata = authorizationFilter.metadata;
// Add Authorizations
siteUsers.canUpdateSiteUsers = await AuthorizationService.canPerformAuthorizationAction(tenant, userToken, Entity.SITE_USER, Action.UPDATE, authorizationFilter);
+ for (const siteUser of siteUsers.result) {
+ await AuthorizationService.addSiteUserAuthorizations(tenant, userToken, siteUser, authorizationFilter);
+ }
+ }
+
+ public static async addSiteUserAuthorizations(tenant: Tenant, userToken: UserToken, siteUser: SiteUser, authorizationFilter: AuthorizationFilter): Promise<void> {
+ siteUser.canAssignToSite = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.SITE_USER, Action.ASSIGN, authorizationFilter, { UserID: siteUser.user.id }, siteUser);
+ siteUser.canUnassignFromSite = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.SITE_USER, Action.UNASSIGN, authorizationFilter, { UserID: siteUser.user.id }, siteUser);
+ // Optimize data over the net
+ Utils.removeCanPropertiesWithFalseValue(siteUser);
+ }
+
+ // eslint-disable-next-line max-len
+ public static async addSiteUserAuthToUserAuthorizations(tenant: Tenant, userToken: UserToken, site: Site, users: User[], authorizationFilter: AuthorizationFilter): Promise<void> {
+ for (const user of users) {
+ user.canAssignToSite = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.SITE_USER, Action.ASSIGN_USERS_TO_SITE, authorizationFilter, { UserID: user.id }, site);
+ user.canUnassignFromSite = await AuthorizationService.canPerformAuthorizationAction(
+ tenant, userToken, Entity.SITE_USER, Action.UNASSIGN_USERS_FROM_SITE, authorizationFilter, { UserID: user.id }, site);
+ // Optimize data over the net
+ Utils.removeCanPropertiesWithFalseValue(site);
+ }
}
public static async addSitesAuthorizations(tenant: Tenant, userToken: UserToken, sites: SiteDataResult, authorizationFilter: AuthorizationFilter): Promise<void> {
@@ -148,6 +196,7 @@ export default class AuthorizationService {
return authorizations;
}
+ // LIST
public static async checkAndGetSiteUsersAuthorizations(tenant: Tenant, userToken: UserToken,
filteredRequest: Partial<HttpSiteUsersRequest>, failsWithException = true): Promise<AuthorizationFilter> {
const authorizations: AuthorizationFilter = {
@@ -156,12 +205,15 @@ export default class AuthorizationService {
projectFields: [],
authorized: false,
};
+ // Filter projected fields
+ authorizations.projectFields = AuthorizationService.filterProjectFields(authorizations.projectFields, filteredRequest.ProjectFields);
// Check static & dynamic authorization
await this.canPerformAuthorizationAction(tenant, userToken, Entity.SITE_USER, Action.LIST,
authorizations, filteredRequest, null, failsWithException);
return authorizations;
}
+ // LIST
public static async checkAndGetUserSitesAuthorizations(tenant: Tenant, userToken : UserToken,
filteredRequest: Partial<HttpUserSitesRequest>): Promise<AuthorizationFilter> {
const authorizations: AuthorizationFilter = {
@@ -178,6 +230,7 @@ export default class AuthorizationService {
return authorizations;
}
+ // ASSIGN/UNASSIGN USERS TO/FROM SITE
public static async checkAssignSiteUsersAuthorizations(tenant: Tenant, action: ServerAction, userToken: UserToken,
filteredRequest: Partial<HttpSiteAssignUsersRequest>): Promise<AuthorizationFilter> {
const authorizations: AuthorizationFilter = {
@@ -193,17 +246,18 @@ export default class AuthorizationService {
return authorizations;
}
- public static async checkAndAssignUserSitesAuthorizations(
+ // ASSIGN/UNASSIGN SITES TO/FROM USER
+ public static async checkAssignUserSitesAuthorizations(
tenant: Tenant, action: ServerAction, userToken: UserToken,
filteredRequest: Partial<HttpUserAssignSitesRequest>): Promise<AuthorizationFilter> {
const authorizations: AuthorizationFilter = {
filters: {},
dataSources: new Map(),
projectFields: [],
- authorized: userToken.role === UserRole.ADMIN,
+ authorized: false,
};
// Check static & dynamic authorization
- const authAction = action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN : Action.UNASSIGN;
+ const authAction = action === ServerAction.ADD_SITES_TO_USER ? Action.ASSIGN_SITES_TO_USER : Action.UNASSIGN_SITES_FROM_USER;
await this.canPerformAuthorizationAction(tenant, userToken, Entity.USER_SITE, authAction,
authorizations, filteredRequest, null, true);
return authorizations;

MODIFY
src/server/rest/v1/service/SiteService.ts
src/server/rest/v1/service/SiteService.ts
import { Action, Entity } from '../../../../types/Authorization';
+import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError';
import { NextFunction, Request, Response } from 'express';
import { SiteDataResult, SiteUserDataResult } from '../../../../types/DataResult';
+import AppAuthError from '../../../../exception/AppAuthError';
import AppError from '../../../../exception/AppError';
import AuthorizationService from './AuthorizationService';
import ChargingStationStorage from '../../../../storage/mongodb/ChargingStationStorage';
import Constants from '../../../../utils/Constants';
-import { HTTPError } from '../../../../types/HTTPError';
import Logging from '../../../../utils/Logging';
import LoggingHelper from '../../../../utils/LoggingHelper';
import { ServerAction } from '../../../../types/Server';
@@ -28,15 +29,6 @@ export default class SiteService {
Action.UPDATE, Entity.SITE, MODULE_NAME, 'handleUpdateSiteUserAdmin');
// Filter request
const filteredRequest = SiteValidator.getInstance().validateSiteAdminReq(req.body);
- if (req.user.id === filteredRequest.userID) {
- throw new AppError({
- errorCode: HTTPError.GENERAL_ERROR,
- message: 'Cannot change the site Admin on the logged user',
- module: MODULE_NAME, method: 'handleUpdateSiteUserAdmin',
- user: req.user,
- actionOnUser: filteredRequest.userID
- });
- }
// Check and Get Site
const site = await UtilsService.checkAndGetSiteAuthorization(
req.tenant, req.user, filteredRequest.siteID, Action.UPDATE, action);
@@ -97,8 +89,32 @@ export default class SiteService {
req.tenant, req.user, site, filteredRequest.userIDs, action);
// Save
if (action === ServerAction.ADD_USERS_TO_SITE) {
+ for (const user of users) {
+ const authorized = AuthorizationService.canPerformAction(user, Action.ASSIGN_USERS_TO_SITE);
+ if (!authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.ASSIGN_USERS_TO_SITE, entity: Entity.SITE_USER,
+ module: MODULE_NAME, method: 'handleAssignUsersToSite',
+ value: site.id
+ });
+ }
+ }
await SiteStorage.addUsersToSite(req.tenant, site.id, users.map((user) => user.id));
} else {
+ for (const user of users) {
+ const authorized = AuthorizationService.canPerformAction(user, Action.UNASSIGN_USERS_FROM_SITE);
+ if (!authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.UNASSIGN_USERS_FROM_SITE, entity: Entity.SITE_USER,
+ module: MODULE_NAME, method: 'handleAssignUsersToSite',
+ value: site.id
+ });
+ }
+ }
await SiteStorage.removeUsersFromSite(req.tenant, site.id, users.map((user) => user.id));
}
await Logging.logInfo({

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -117,8 +117,32 @@ export default class UserService {
req.tenant, req.user, user, filteredRequest.siteIDs, action);
// Save
if (action === ServerAction.ADD_SITES_TO_USER) {
+ for (const site of sites) {
+ const authorized = AuthorizationService.canPerformAction(site, Action.ASSIGN_SITES_TO_USER);
+ if (!authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.ASSIGN_SITES_TO_USER, entity: Entity.USER_SITE,
+ module: MODULE_NAME, method: 'checkAndGetPricingDefinitionAuthorization',
+ value: site.id
+ });
+ }
+ }
await UserStorage.addSitesToUser(req.tenant, filteredRequest.userID, sites.map((site) => site.id));
} else {
+ for (const site of sites) {
+ const authorized = AuthorizationService.canPerformAction(site, Action.UNASSIGN_SITES_FROM_USER);
+ if (!authorized) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.ASSIGN_USERS_TO_SITE, entity: Entity.USER_SITE,
+ module: MODULE_NAME, method: 'checkAndGetPricingDefinitionAuthorization',
+ value: site.id
+ });
+ }
+ }
await UserStorage.removeSitesFromUser(req.tenant, filteredRequest.userID, sites.map((site) => site.id));
}
// Log

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
import { Action, AuthorizationFilter, Entity } from '../../../../types/Authorization';
import { Car, CarCatalog } from '../../../../types/Car';
import ChargingStation, { ChargePoint } from '../../../../types/ChargingStation';
+import { DataResult, UserSiteDataResult } from '../../../../types/DataResult';
import { HTTPAuthError, HTTPError } from '../../../../types/HTTPError';
import { NextFunction, Request, Response } from 'express';
import Tenant, { TenantComponents } from '../../../../types/Tenant';
@@ -24,7 +25,6 @@ import Company from '../../../../types/Company';
import CompanyStorage from '../../../../storage/mongodb/CompanyStorage';
import Constants from '../../../../utils/Constants';
import Cypher from '../../../../utils/Cypher';
-import { DataResult } from '../../../../types/DataResult';
import { EntityData } from '../../../../types/GlobalType';
import { Log } from '../../../../types/Log';
import LogStorage from '../../../../storage/mongodb/LogStorage';
@@ -458,7 +458,7 @@ export default class UtilsService {
});
}
// Check dynamic auth for assignment
- const authorizations = await AuthorizationService.checkAndAssignUserSitesAuthorizations(
+ const authorizations = await AuthorizationService.checkAssignUserSitesAuthorizations(
tenant, action, userToken, { userID: user.id, siteIDs });
// Get Sites
let sites = (await SiteStorage.getSites(tenant,
@@ -481,6 +481,7 @@ export default class UtilsService {
module: MODULE_NAME, method: 'checkUserSitesAuthorization',
});
}
+ await AuthorizationService.addUserSiteAuthToSitesAuthorizations(tenant, userToken, user, sites, authorizations);
return sites;
}
@@ -515,11 +516,12 @@ export default class UtilsService {
throw new AppAuthError({
errorCode: HTTPAuthError.FORBIDDEN,
user: userToken,
- action: action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN : Action.UNASSIGN,
- entity: Entity.USER_SITE,
- module: MODULE_NAME, method: 'checkSiteUsersAuthorization',
+ action: action === ServerAction.ADD_USERS_TO_SITE ? Action.ASSIGN_USERS_TO_SITE : Action.UNASSIGN_USERS_FROM_SITE,
+ entity: Entity.SITE_USER,
+ module: MODULE_NAME, method: 'checkAndGetSiteUsersAuthorization',
});
}
+ await AuthorizationService.addSiteUserAuthToUserAuthorizations(tenant, userToken, site, users, authorizations);
return users;
}

MODIFY
src/types/Authorization.ts
src/types/Authorization.ts
@@ -148,8 +148,10 @@ export enum Action {
TRIGGER_JOB = 'TriggerJob',
DOWNLOAD = 'Download',
IMPORT = 'Import',
- ASSIGN_USERS_TO_SITE = 'AssignUsers',
- UNASSIGN_USERS_FROM_SITE = 'UnassignUsers',
+ ASSIGN_USERS_TO_SITE = 'AssignToSite',
+ UNASSIGN_USERS_FROM_SITE = 'UnassignFromSite',
+ ASSIGN_SITES_TO_USER = 'AssignToUser',
+ UNASSIGN_SITES_FROM_USER = 'UnassignFromUser',
ASSIGN_ASSETS_TO_SITE_AREA = 'AssignAssets',
UNASSIGN_ASSETS_FROM_SITE_AREA = 'UnassignAssets',
READ_ASSETS_FROM_SITE_AREA = 'ReadAssets',
@@ -193,12 +195,24 @@ export interface AuthorizationActions {
export interface UserAuthorizationActions extends AuthorizationActions {
canAssignSites?: boolean;
canUnassignSites?: boolean;
+ canAssignToSite?: boolean;
+ canUnassignFromSite?: boolean;
canListUserSites?: boolean;
canListTags?: boolean;
canListTransactions?: boolean;
canSynchronizeBillingUser?: boolean;
}
+export interface UserSiteAuthorizationActions extends AuthorizationActions {
+ canAssignToUser?: boolean;
+ canUnassignFromUser?: boolean;
+}
+
+export interface SiteUserAuthorizationActions extends AuthorizationActions {
+ canAssignToSite?: boolean;
+ canUnassignFromSite?: boolean;
+}
+
export interface TagAuthorizationActions extends AuthorizationActions {
canUnassign?: boolean;
canAssign?: boolean;
@@ -230,6 +244,8 @@ export interface SiteAreaAuthorizationActions extends AuthorizationActions {
export interface SiteAuthorizationActions extends AuthorizationActions {
canAssignUsers?: boolean;
canUnassignUsers?: boolean;
+ canAssignToUser?: boolean;
+ canUnassignFromUser?: boolean;
canListSiteUsers?: boolean;
canExportOCPPParams?: boolean;
canGenerateQrCode?: boolean;

MODIFY
src/types/GlobalType.ts
src/types/GlobalType.ts
import { BillingInvoice, BillingPaymentMethod } from './Billing';
import { Car, CarCatalog } from './Car';
+import Site, { UserSite } from './Site';
+import User, { SiteUser } from './User';
import ChargingStation from './ChargingStation';
import Company from './Company';
@@ -10,11 +12,9 @@ import PricingDefinition from './Pricing';
import RegistrationToken from './RegistrationToken';
import { ServerType } from './Server';
import { Setting } from './Setting';
-import Site from './Site';
import SiteArea from './SiteArea';
import SoapOCPPServer from '../server/ocpp/soap/SoapOCPPServer';
import Tag from './Tag';
-import User from './User';
import bluebird from 'bluebird';
import path from 'path';
@@ -76,7 +76,7 @@ export enum ImportStatus {
ERROR = 'E',
}
-export type EntityData = Car|User|Company|Site|SiteArea|Tag|CarCatalog|ChargingStation|PricingDefinition|Log|RegistrationToken|BillingInvoice|BillingPaymentMethod|Setting;
+export type EntityData = Car|User|Company|Site|SiteArea|Tag|CarCatalog|ChargingStation|PricingDefinition|Log|RegistrationToken|BillingInvoice|BillingPaymentMethod|Setting|UserSite|SiteUser;
interface TSGlobal extends Global {
database: MongoDBStorage;

MODIFY
src/types/Site.ts
src/types/Site.ts
+import { SiteAuthorizationActions, UserSiteAuthorizationActions } from './Authorization';
+
import Address from './Address';
import Company from './Company';
import ConnectorStats from './ConnectorStats';
@@ -5,7 +7,6 @@ import CreatedUpdatedProps from './CreatedUpdatedProps';
import { OCPILocation } from './ocpi/OCPILocation';
import { OpeningTimes } from './OpeningTimes';
import SiteArea from './SiteArea';
-import { SiteAuthorizationActions } from './Authorization';
export default interface Site extends CreatedUpdatedProps, SiteAuthorizationActions {
id: string;
@@ -24,7 +25,7 @@ export default interface Site extends CreatedUpdatedProps, SiteAuthorizationActi
tariffID?: string;
}
-export interface UserSite {
+export interface UserSite extends UserSiteAuthorizationActions{
site: Site;
siteID?: string;
userID: string;

MODIFY
src/types/User.ts
src/types/User.ts
+import { SiteUserAuthorizationActions, UserAuthorizationActions } from './Authorization';
+
import Address from './Address';
import { BillingUserData } from './Billing';
import CreatedUpdatedProps from './CreatedUpdatedProps';
import { ImportStatus } from './GlobalType';
-import { UserAuthorizationActions } from './Authorization';
import UserNotifications from './UserNotifications';
export default interface User extends CreatedUpdatedProps, UserAuthorizationActions {
@@ -54,7 +55,7 @@ export interface StartTransactionUserData {
lastDepartureTime: Date;
}
-export interface SiteUser {
+export interface SiteUser extends SiteUserAuthorizationActions {
user: User;
userID?: string;
siteID: string;

assign/unassign working