diff --git a/src/models/group.ts b/src/models/group.ts index e52552d103de7a583a2618b4ba9b8f6aadac4796..6d5be6422207bd31153597a43832eb07506d232b 100644 --- a/src/models/group.ts +++ b/src/models/group.ts @@ -4,6 +4,7 @@ import { Channel } from './channel'; import { User } from './user'; import { Notification } from './notification'; import { CERNActiveDirectory, EGroupRestrictions } from './cern-activedirectory'; +import { ForbiddenError } from 'routing-controllers'; @Entity({ name: 'Groups' }) @Unique(['groupIdentifier']) @@ -41,4 +42,48 @@ export class Group { async getRestrictions(): Promise<EGroupRestrictions | null> { return await CERNActiveDirectory.memoizedGetGroupRestrictions(this.groupIdentifier); } + + async validateEgroupPostingRestrictionsOrThrowError(userName: string, userGroups: any[]): Promise<void> { + // If restrictions are set, deny adding to people not in the restriction list or admins of the EGroup. + const restrictions = await this.getRestrictions(); + console.debug('restrictions', restrictions); + + if (!restrictions) { + return; + } + + // Restrictions are set on this e-group + // Check if current user trying to add is: + // - Owner or member of e-group admins + // - Listed in the restrictions, by username or member of another e-group (except e-group members) + if (userName === restrictions.owner) { + console.debug('authorized as e-group owner', userName); + return; + } + + if ( + restrictions.administratorEgroup && + userGroups.some(group => group.groupIdentifier === restrictions.administratorEgroup) + ) { + console.debug('authorized as e-group admins member', userName); + return; + } + + if (restrictions.postingUsers && restrictions.postingUsers.includes(userName)) { + console.debug('authorized as e-group restrictionUser member', userName); + return; + } + + if ( + restrictions.postingGroups && + userGroups.some(group => restrictions.postingGroups.includes(group.groupIdentifier)) + ) { + console.debug('authorized as e-group restrictionGroups member', userName); + return; + } + + throw new ForbiddenError( + `E-group ${this.groupIdentifier} has posting restrictions and you don't have the rights to use it.`, + ); + } } diff --git a/src/services/impl/channels/add-group-to-channel.ts b/src/services/impl/channels/add-group-to-channel.ts index f12b7ff4e8810bda15a195b7e143b94051bd8d43..54e82a2ba173042eb90cc116ea53f8c4782b8959 100644 --- a/src/services/impl/channels/add-group-to-channel.ts +++ b/src/services/impl/channels/add-group-to-channel.ts @@ -35,7 +35,7 @@ export class AddGroupToChannel implements Command { } // Throws error if there's an un-matched EGroup posting restriction - await this.checkEgroupPostingRestrictions(groupToAdd, userGroups); + await groupToAdd.validateEgroupPostingRestrictionsOrThrowError(this.authorizationBag.userName, userGroups); await channel.addGroup(transactionManager, groupToAdd); await AuditChannels.setValue(channel.id, { @@ -47,48 +47,4 @@ export class AddGroupToChannel implements Command { return new GroupResponse(groupToAdd); } - - async checkEgroupPostingRestrictions(groupToAdd: Group, userGroups: any[]): Promise<void> { - // If restrictions are set, deny adding to people not in the restriction list or admins of the EGroup. - const restrictions = await groupToAdd.getRestrictions(); - console.debug('restrictions', restrictions); - - if (!restrictions) { - return; - } - - // Restrictions are set on this e-group - // Check if current user trying to add is: - // - Owner or member of e-group admins - // - Listed in the restrictions, by username or member of another e-group (except e-group members) - if (this.authorizationBag.userName === restrictions.owner) { - console.debug('authorized as e-group owner', this.authorizationBag.userName); - return; - } - - if ( - restrictions.administratorEgroup && - userGroups.some(group => group.groupIdentifier === restrictions.administratorEgroup) - ) { - console.debug('authorized as e-group admins member', this.authorizationBag.userName); - return; - } - - if (restrictions.postingUsers && restrictions.postingUsers.includes(this.authorizationBag.userName)) { - console.debug('authorized as e-group restrictionUser member', this.authorizationBag.userName); - return; - } - - if ( - restrictions.postingGroups && - userGroups.some(group => restrictions.postingGroups.includes(group.groupIdentifier)) - ) { - console.debug('authorized as e-group restrictionGroups member', this.authorizationBag.userName); - return; - } - - throw new ForbiddenError( - `E-group ${this.groupName} has posting restrictions and you don't have the rights to use it.`, - ); - } } diff --git a/src/services/impl/notifications/send-notification.ts b/src/services/impl/notifications/send-notification.ts index bfd30b7a70966dad7e4301c6055167310e5180f1..89631e07a79d4e0b775924a55fb590f6440b6277 100644 --- a/src/services/impl/notifications/send-notification.ts +++ b/src/services/impl/notifications/send-notification.ts @@ -28,16 +28,13 @@ export class SendNotification implements Command { constructor(private notification: SendNotificationRequest, private authorizationBag: AuthorizationBag) {} - async hasAccess(transactionManager: EntityManager, channel: Channel): Promise<boolean> { + async hasAccess(transactionManager: EntityManager, channel: Channel, userGroups: any[]): Promise<boolean> { if (!this.authorizationBag) { // Call from the /unauthenticated // restricted by direct access in openshift return true; } - // Get current user groups, to be used next in SQL to compare with channel groups - const userGroups = await CernAuthorizationService.getCurrentUserGroups(this.authorizationBag.userName); - const hasApiKeyAccess = channel.hasApiKeyAccess(this.authorizationBag); console.debug('hasApiKeyAccess', hasApiKeyAccess); if (hasApiKeyAccess) return true; @@ -84,7 +81,10 @@ export class SendNotification implements Command { throw new NotFoundError('Channel does not exist'); } - if (!(await this.hasAccess(transactionManager, targetChannel))) { + // Get current user groups, to be used next in SQL to compare with channel groups + const userGroups = await CernAuthorizationService.getCurrentUserGroups(this.authorizationBag.userName); + + if (!(await this.hasAccess(transactionManager, targetChannel, userGroups))) { throw new ForbiddenError('Sending to Channel not Authorized !'); } @@ -140,6 +140,7 @@ export class SendNotification implements Command { transactionManager, targetChannel, this.notification.intersection, + userGroups, ); } @@ -181,7 +182,7 @@ export class SendNotification implements Command { }); // eslint-disable-next-line no-empty } catch (any) { - console.exception(any); + console.error(any); } // Get back object from DB, without full info about target Channel @@ -330,6 +331,7 @@ export class SendNotification implements Command { transactionManager: EntityManager, channel: Channel, intersection: boolean, + userGroups: any[], ): Promise<Group[]> { if (!channel.sendPrivate) throw new ForbiddenError('This Channel does not allow direct notifications'); @@ -346,6 +348,9 @@ export class SendNotification implements Command { throw new BadRequestError('Grappa group not found: ' + groupIdentifier); } + // Throws error if there's an un-matched EGroup posting restriction + await group.validateEgroupPostingRestrictionsOrThrowError(this.authorizationBag.userName, userGroups); + targetGroups.push(group); if (intersection) return;