diff --git a/apps/meteor/app/statistics/server/lib/statistics.ts b/apps/meteor/app/statistics/server/lib/statistics.ts index 0fadf701d4657..73292480d74f4 100644 --- a/apps/meteor/app/statistics/server/lib/statistics.ts +++ b/apps/meteor/app/statistics/server/lib/statistics.ts @@ -4,6 +4,7 @@ import os from 'os'; import { Analytics, Team, VideoConf, Presence } from '@rocket.chat/core-services'; import type { IRoom, IStats, ISetting } from '@rocket.chat/core-typings'; import { UserStatus } from '@rocket.chat/core-typings'; +import { License } from '@rocket.chat/license'; import { NotificationQueue, Rooms, @@ -25,6 +26,7 @@ import { Subscriptions, Users, LivechatRooms, + AbacAttributes, } from '@rocket.chat/models'; import { MongoInternals } from 'meteor/mongo'; import moment from 'moment'; @@ -609,6 +611,26 @@ export const statistics = { statistics.webRTCEnabledForOmnichannel = settings.get('Omnichannel_call_provider') === 'WebRTC'; statistics.omnichannelWebRTCCalls = await Rooms.findCountOfRoomsWithActiveCalls(); + // ABAC stats + if (License.hasModule('abac')) { + statistics.abacEnabled = settings.get('ABAC_Enabled'); + statsPms.push( + AbacAttributes.estimatedDocumentCount().then((result) => { + statistics.abacTotalAttributes = result; + }), + ); + statsPms.push( + AbacAttributes.countTotalValues().then((result) => { + statistics.abacTotalAttributeValues = result; + }), + ); + statsPms.push( + Rooms.countAbacEnabled().then((result) => { + statistics.abacRoomsEnrolled = result; + }), + ); + } + await Promise.all(statsPms).catch(log); return statistics; diff --git a/packages/core-typings/src/IStats.ts b/packages/core-typings/src/IStats.ts index a940be16fd374..bee28ac0ddf1c 100644 --- a/packages/core-typings/src/IStats.ts +++ b/packages/core-typings/src/IStats.ts @@ -271,4 +271,8 @@ export interface IStats { totalUpsellViews: number; totalUpsellClicks: number; }; + abacEnabled?: boolean; + abacTotalAttributes?: number; + abacTotalAttributeValues?: number; + abacRoomsEnrolled?: number; } diff --git a/packages/model-typings/src/models/IAbacAttributesModel.ts b/packages/model-typings/src/models/IAbacAttributesModel.ts index 6e1ae5050ee59..485aa7bae751a 100644 --- a/packages/model-typings/src/models/IAbacAttributesModel.ts +++ b/packages/model-typings/src/models/IAbacAttributesModel.ts @@ -6,4 +6,5 @@ import type { IBaseModel } from './IBaseModel'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IAbacAttributesModel extends IBaseModel { findOneByKey(key: string, options?: FindOptions): Promise; + countTotalValues(): Promise; } diff --git a/packages/model-typings/src/models/IRoomsModel.ts b/packages/model-typings/src/models/IRoomsModel.ts index 7f10b3e06f2f3..d0d9f183bcf61 100644 --- a/packages/model-typings/src/models/IRoomsModel.ts +++ b/packages/model-typings/src/models/IRoomsModel.ts @@ -125,6 +125,8 @@ export interface IRoomsModel extends IBaseModel { findByBroadcast(options?: FindOptions): FindCursor; + countAbacEnabled(): Promise; + setAsFederated(roomId: IRoom['_id'], { mrid, origin }: { mrid: string; origin: string }): Promise; setRoomTypeById(roomId: IRoom['_id'], roomType: IRoom['t']): Promise; diff --git a/packages/models/src/models/AbacAttributes.ts b/packages/models/src/models/AbacAttributes.ts index 5ced8887ddfb0..24d1cf7aa46a8 100644 --- a/packages/models/src/models/AbacAttributes.ts +++ b/packages/models/src/models/AbacAttributes.ts @@ -15,4 +15,25 @@ export class AbacAttributesRaw extends BaseRaw { findOneByKey(key: string, options: FindOptions = {}): Promise { return this.findOne({ key }, options); } + + async countTotalValues(): Promise { + const [result] = await this.col + .aggregate<{ totalValues: number }>([ + { + $group: { + _id: null, + totalValues: { + $sum: { + $size: { + $ifNull: ['$values', []], + }, + }, + }, + }, + }, + ]) + .toArray(); + + return result?.totalValues ?? 0; + } } diff --git a/packages/models/src/models/Rooms.ts b/packages/models/src/models/Rooms.ts index 3dbfea10cdff2..7d28f32f63c32 100644 --- a/packages/models/src/models/Rooms.ts +++ b/packages/models/src/models/Rooms.ts @@ -2312,4 +2312,8 @@ export class RoomsRaw extends BaseRaw implements IRoomsModel { // TODO implement return []; } + + countAbacEnabled(): Promise { + return this.countDocuments({ abacAttributes: { $exists: true }, archived: { $ne: true } }); + } }