[NEW] New stats rewrite (#25078)

Co-authored-by: matheusbsilva137 <matheus_barbosa137@hotmail.com>
Co-authored-by: Diego Sampaio <chinello@gmail.com>
pull/25573/head
Leonardo Ostjen Couto 4 years ago committed by GitHub
parent 42442d22be
commit b893ffdc20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      apps/meteor/app/importer-csv/server/importer.js
  2. 2
      apps/meteor/app/importer-hipchat-enterprise/server/importer.js
  3. 2
      apps/meteor/app/importer-slack-users/server/importer.js
  4. 3
      apps/meteor/app/importer-slack/server/importer.js
  5. 6
      apps/meteor/app/lib/server/methods/sendInvitationEmail.js
  6. 5
      apps/meteor/app/lib/server/startup/email.ts
  7. 20
      apps/meteor/app/lib/server/startup/settings.ts
  8. 1
      apps/meteor/app/models/server/models/Rooms.js
  9. 4
      apps/meteor/app/models/server/models/Settings.js
  10. 3
      apps/meteor/app/models/server/models/Users.js
  11. 8
      apps/meteor/app/models/server/raw/Invites.ts
  12. 42
      apps/meteor/app/models/server/raw/Messages.js
  13. 17
      apps/meteor/app/models/server/raw/Rooms.js
  14. 16
      apps/meteor/app/models/server/raw/Users.js
  15. 10
      apps/meteor/app/statistics/server/lib/getImporterStatistics.ts
  16. 45
      apps/meteor/app/statistics/server/lib/getServicesStatistics.ts
  17. 26
      apps/meteor/app/statistics/server/lib/statistics.ts
  18. 25
      apps/meteor/client/views/admin/info/DeploymentCard.stories.tsx
  19. 25
      apps/meteor/client/views/admin/info/InformationPage.stories.tsx
  20. 25
      apps/meteor/client/views/admin/info/UsageCard.stories.tsx
  21. 4
      apps/meteor/client/views/admin/users/AddUser.js
  22. 3
      apps/meteor/server/sdk/types/ITeamService.ts
  23. 44
      apps/meteor/server/services/team/service.ts
  24. 19
      packages/core-typings/src/IStats.ts
  25. 13
      packages/core-typings/src/ITeam.ts

@ -1,7 +1,7 @@
import { Random } from 'meteor/random';
import { Base, ProgressStep, ImporterWebsocket } from '../../importer/server';
import { Users } from '../../models/server';
import { Users, Settings as SettingsRaw } from '../../models/server';
export class CsvImporter extends Base {
constructor(info, importRecord) {
@ -119,7 +119,8 @@ export class CsvImporter extends Base {
});
}
super.updateRecord({ 'count.users': parsedUsers.length });
SettingsRaw.incrementValueById('CSV_Importer_Count', usersCount);
super.updateRecord({ 'count.users': usersCount });
return increaseProgressCount();
}

@ -5,6 +5,7 @@ import fs from 'fs';
import { Meteor } from 'meteor/meteor';
import { Base, ProgressStep } from '../../importer/server';
import { Settings as SettingsRaw } from '../../models/server';
export class HipChatEnterpriseImporter extends Base {
constructor(info, importRecord) {
@ -52,6 +53,7 @@ export class HipChatEnterpriseImporter extends Base {
this.converter.addUser(newUser);
}
SettingsRaw.incrementValueById('Hipchat_Enterprise_Importer_Count', count);
super.updateRecord({ 'count.users': count });
super.addCountToTotal(count);
}

@ -5,6 +5,7 @@ import { Random } from 'meteor/random';
import { RawImports, Base, ProgressStep, Selection, SelectionUser } from '../../importer/server';
import { RocketChatFile } from '../../file';
import { Users } from '../../models';
import { Settings as SettingsRaw } from '../../models/server';
export class SlackUsersImporter extends Base {
constructor(info, importRecord) {
@ -164,6 +165,7 @@ export class SlackUsersImporter extends Base {
});
}
SettingsRaw.incrementValueById('Slack_Users_Importer_Count', this.users.users.length);
super.updateProgress(ProgressStep.FINISHING);
super.updateProgress(ProgressStep.DONE);
} catch (e) {

@ -1,7 +1,7 @@
import _ from 'underscore';
import { Base, ProgressStep, ImporterWebsocket } from '../../importer/server';
import { Messages, ImportData } from '../../models/server';
import { Messages, ImportData, Settings as SettingsRaw } from '../../models/server';
import { settings } from '../../settings/server';
import { MentionsParser } from '../../mentions/lib/MentionsParser';
import { getUserAvatarURL } from '../../utils/lib/getUserAvatarURL';
@ -155,6 +155,7 @@ export class SlackImporter extends Base {
}
this.converter.addUser(newUser);
SettingsRaw.incrementValueById('Slack_Importer_Count');
}
}

@ -4,6 +4,7 @@ import { check } from 'meteor/check';
import * as Mailer from '../../../mailer';
import { hasPermission } from '../../../authorization';
import { settings } from '../../../settings';
import { Settings as SettingsRaw } from '../../../models/server';
let html = '';
Meteor.startup(() => {
@ -37,7 +38,7 @@ Meteor.methods({
return validEmails.filter((email) => {
try {
return Mailer.send({
const mailerResult = Mailer.send({
to: email,
from: settings.get('From_Email'),
subject,
@ -46,6 +47,9 @@ Meteor.methods({
email,
},
});
SettingsRaw.incrementValueById('Invitation_Email_Count');
return mailerResult;
} catch ({ message }) {
throw new Meteor.Error('error-email-send-failed', `Error trying to send email: ${message}`, {
method: 'sendInvitationEmail',

@ -474,6 +474,11 @@ settingsRegistry.addGroup('Email', function () {
);
});
this.add('Invitation_Email_Count', 0, {
type: 'int',
hidden: true,
});
this.section('Forgot_password_section', function () {
this.add('Forgot_Password_Email_Subject', '{Forgot_Password_Email_Subject}', {
type: 'string',

@ -180,6 +180,26 @@ settingsRegistry.addGroup('Accounts', function () {
type: 'string',
hidden: true,
});
this.add('Manual_Entry_User_Count', 0, {
type: 'int',
hidden: true,
});
this.add('CSV_Importer_Count', 0, {
type: 'int',
hidden: true,
});
this.add('Hipchat_Enterprise_Importer_Count', 0, {
type: 'int',
hidden: true,
});
this.add('Slack_Importer_Count', 0, {
type: 'int',
hidden: true,
});
this.add('Slack_Users_Importer_Count', 0, {
type: 'int',
hidden: true,
});
this.add('Accounts_UseDefaultBlockedDomainsList', true, {
type: 'boolean',
});

@ -26,6 +26,7 @@ export class Rooms extends Base {
// field used for DMs only
this.tryEnsureIndex({ uids: 1 }, { sparse: true });
this.tryEnsureIndex({ createdOTR: 1 }, { sparse: true });
this.tryEnsureIndex({ encrypted: 1 }, { sparse: true }); // used on statistics
this.tryEnsureIndex(
{

@ -145,7 +145,7 @@ export class Settings extends Base {
return this.update(query, update);
}
incrementValueById(_id) {
incrementValueById(_id, value = 1) {
const query = {
blocked: { $ne: true },
_id,
@ -153,7 +153,7 @@ export class Settings extends Base {
const update = {
$inc: {
value: 1,
value,
},
};

@ -60,6 +60,9 @@ export class Users extends Base {
this.tryEnsureIndex({ extension: 1 }, { sparse: true, unique: true });
this.tryEnsureIndex({ language: 1 }, { sparse: true });
this.tryEnsureIndex({ 'active': 1, 'services.email2fa.enabled': 1 }, { sparse: true }); // used by statistics
this.tryEnsureIndex({ 'active': 1, 'services.totp.enabled': 1 }, { sparse: true }); // used by statistics
const collectionObj = this.model.rawCollection();
this.findAndModify = Meteor.wrapAsync(collectionObj.findAndModify, collectionObj);
}

@ -27,4 +27,12 @@ export class InvitesRaw extends BaseRaw<T> {
},
);
}
async countUses(): Promise<number> {
const [result] = await this.col
.aggregate<{ totalUses: number } | undefined>([{ $group: { _id: null, totalUses: { $sum: '$uses' } } }])
.toArray();
return result?.totalUses || 0;
}
}

@ -188,4 +188,46 @@ export class MessagesRaw extends BaseRaw {
options,
);
}
async countRoomsWithStarredMessages(options) {
const [queryResult] = await this.col
.aggregate(
[{ $match: { 'starred._id': { $exists: true } } }, { $group: { _id: '$rid' } }, { $group: { _id: null, total: { $sum: 1 } } }],
options,
)
.toArray();
return queryResult?.total || 0;
}
async countRoomsWithPinnedMessages(options) {
const [queryResult] = await this.col
.aggregate([{ $match: { pinned: true } }, { $group: { _id: '$rid' } }, { $group: { _id: null, total: { $sum: 1 } } }], options)
.toArray();
return queryResult?.total || 0;
}
async countE2EEMessages(options) {
return this.find({ t: 'e2e' }, options).count();
}
findPinned(options) {
const query = {
t: { $ne: 'rm' },
_hidden: { $ne: true },
pinned: true,
};
return this.find(query, options);
}
findStarred(options) {
const query = {
'_hidden': { $ne: true },
'starred._id': { $exists: true },
};
return this.find(query, options);
}
}

@ -460,4 +460,21 @@ export class RoomsRaw extends BaseRaw {
},
]);
}
findByE2E(options) {
return this.find(
{
encrypted: true,
},
options,
);
}
findRoomsInsideTeams(autoJoin = false) {
return this.find({
teamId: { $exists: true },
teamMain: { $exists: false },
...(autoJoin && { teamDefault: true }),
});
}
}

@ -999,4 +999,20 @@ export class UsersRaw extends BaseRaw {
return this.find(query, options);
}
findActiveUsersTOTPEnable(options) {
const query = {
'active': true,
'services.totp.enabled': true,
};
return this.find(query, options);
}
findActiveUsersEmail2faEnable(options) {
const query = {
'active': true,
'services.email2fa.enabled': true,
};
return this.find(query, options);
}
}

@ -0,0 +1,10 @@
import { settings } from '../../../settings/server';
export function getImporterStatistics(): Record<string, unknown> {
return {
totalCSVImportedUsers: settings.get('CSV_Importer_Count'),
totalHipchatEnterpriseImportedUsers: settings.get('Hipchat_Enterprise_Importer_Count'),
totalSlackImportedUsers: settings.get('Slack_Importer_Count'),
totalSlackUsersImportedUsers: settings.get('Slack_Users_Importer_Count'),
};
}

@ -1,6 +1,11 @@
import { MongoInternals } from 'meteor/mongo';
import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred';
import { settings } from '../../../settings/server';
import { Users } from '../../../models/server';
const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;
function getCustomOAuthServices(): Record<
string,
{
@ -9,6 +14,8 @@ function getCustomOAuthServices(): Record<
users: number;
}
> {
const readPreference = readSecondaryPreferred(db);
const customOauth = settings.getByRegexp(/Accounts_OAuth_Custom-[^-]+$/im);
return Object.fromEntries(
Object.entries(customOauth).map(([key, value]) => {
@ -18,7 +25,7 @@ function getCustomOAuthServices(): Record<
{
enabled: Boolean(value),
mergeRoles: settings.get<boolean>(`Accounts_OAuth_Custom-${name}-merge_roles`),
users: Users.countActiveUsersByService(name),
users: Users.countActiveUsersByService(name, { readPreference }),
},
];
}),
@ -26,9 +33,11 @@ function getCustomOAuthServices(): Record<
}
export function getServicesStatistics(): Record<string, unknown> {
const readPreference = readSecondaryPreferred(db);
return {
ldap: {
users: Users.countActiveUsersByService('ldap'),
users: Users.countActiveUsersByService('ldap', { readPreference }),
enabled: settings.get('LDAP_Enable'),
loginFallback: settings.get('LDAP_Login_Fallback'),
encryption: settings.get('LDAP_Encryption'),
@ -53,7 +62,7 @@ export function getServicesStatistics(): Record<string, unknown> {
},
saml: {
enabled: settings.get('SAML_Custom_Default'),
users: Users.countActiveUsersByService('saml'),
users: Users.countActiveUsersByService('saml', { readPreference }),
signatureValidationType: settings.get('SAML_Custom_Default_signature_validation_type'),
generateUsername: settings.get('SAML_Custom_Default_generate_username'),
updateSubscriptionsOnLogin: settings.get('SAML_Custom_Default_channels_update'),
@ -61,66 +70,66 @@ export function getServicesStatistics(): Record<string, unknown> {
},
cas: {
enabled: settings.get('CAS_enabled'),
users: Users.countActiveUsersByService('cas'),
users: Users.countActiveUsersByService('cas', { readPreference }),
allowUserCreation: settings.get('CAS_Creation_User_Enabled'),
alwaysSyncUserData: settings.get('CAS_Sync_User_Data_Enabled'),
},
oauth: {
apple: {
enabled: settings.get('Accounts_OAuth_Apple'),
users: Users.countActiveUsersByService('apple'),
users: Users.countActiveUsersByService('apple', { readPreference }),
},
dolphin: {
enabled: settings.get('Accounts_OAuth_Dolphin'),
users: Users.countActiveUsersByService('dolphin'),
users: Users.countActiveUsersByService('dolphin', { readPreference }),
},
drupal: {
enabled: settings.get('Accounts_OAuth_Drupal'),
users: Users.countActiveUsersByService('drupal'),
users: Users.countActiveUsersByService('drupal', { readPreference }),
},
facebook: {
enabled: settings.get('Accounts_OAuth_Facebook'),
users: Users.countActiveUsersByService('facebook'),
users: Users.countActiveUsersByService('facebook', { readPreference }),
},
github: {
enabled: settings.get('Accounts_OAuth_Github'),
users: Users.countActiveUsersByService('github'),
users: Users.countActiveUsersByService('github', { readPreference }),
},
githubEnterprise: {
enabled: settings.get('Accounts_OAuth_GitHub_Enterprise'),
users: Users.countActiveUsersByService('github_enterprise'),
users: Users.countActiveUsersByService('github_enterprise', { readPreference }),
},
gitlab: {
enabled: settings.get('Accounts_OAuth_Gitlab'),
users: Users.countActiveUsersByService('gitlab'),
users: Users.countActiveUsersByService('gitlab', { readPreference }),
},
google: {
enabled: settings.get('Accounts_OAuth_Google'),
users: Users.countActiveUsersByService('google'),
users: Users.countActiveUsersByService('google', { readPreference }),
},
linkedin: {
enabled: settings.get('Accounts_OAuth_Linkedin'),
users: Users.countActiveUsersByService('linkedin'),
users: Users.countActiveUsersByService('linkedin', { readPreference }),
},
meteor: {
enabled: settings.get('Accounts_OAuth_Meteor'),
users: Users.countActiveUsersByService('meteor'),
users: Users.countActiveUsersByService('meteor', { readPreference }),
},
nextcloud: {
enabled: settings.get('Accounts_OAuth_Nextcloud'),
users: Users.countActiveUsersByService('nextcloud'),
users: Users.countActiveUsersByService('nextcloud', { readPreference }),
},
tokenpass: {
enabled: settings.get('Accounts_OAuth_Tokenpass'),
users: Users.countActiveUsersByService('tokenpass'),
users: Users.countActiveUsersByService('tokenpass', { readPreference }),
},
twitter: {
enabled: settings.get('Accounts_OAuth_Twitter'),
users: Users.countActiveUsersByService('twitter'),
users: Users.countActiveUsersByService('twitter', { readPreference }),
},
wordpress: {
enabled: settings.get('Accounts_OAuth_Wordpress'),
users: Users.countActiveUsersByService('wordpress'),
users: Users.countActiveUsersByService('wordpress', { readPreference }),
},
custom: getCustomOAuthServices(),
},

@ -18,6 +18,7 @@ import {
Statistics,
Sessions,
Integrations,
Invites,
Uploads,
LivechatDepartment,
EmailInbox,
@ -27,9 +28,10 @@ import {
} from '../../../models/server/raw';
import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred';
import { getAppsStatistics } from './getAppsStatistics';
import { getImporterStatistics } from './getImporterStatistics';
import { getServicesStatistics } from './getServicesStatistics';
import { getStatistics as getEnterpriseStatistics } from '../../../../ee/app/license/server';
import { Analytics } from '../../../../server/sdk';
import { Analytics, Team } from '../../../../server/sdk';
import { getSettingsStatistics } from '../../../../server/lib/statistics/getSettingsStatistics';
const wizardFields = ['Organization_Type', 'Industry', 'Size', 'Country', 'Language', 'Server_Type', 'Register_Server'];
@ -395,6 +397,7 @@ export const statistics = {
statistics.apps = getAppsStatistics();
statistics.services = getServicesStatistics();
statistics.importer = getImporterStatistics();
// If getSettingsStatistics() returns an error, save as empty object.
statsPms.push(
@ -448,6 +451,12 @@ export const statistics = {
}),
);
statsPms.push(
Team.getStatistics().then((result) => {
statistics.teams = result;
}),
);
statsPms.push(Analytics.resetSeatRequestCount());
statistics.dashboardCount = settings.get('Engagement_Dashboard_Load_Count');
@ -457,6 +466,21 @@ export const statistics = {
statistics.slashCommandsJitsi = settings.get('Jitsi_Start_SlashCommands_Count');
statistics.totalOTRRooms = Rooms.findByCreatedOTR().count();
statistics.totalOTR = settings.get('OTR_Count');
statistics.totalRoomsWithStarred = await MessagesRaw.countRoomsWithStarredMessages({ readPreference });
statistics.totalRoomsWithPinned = await MessagesRaw.countRoomsWithPinnedMessages({ readPreference });
statistics.totalUserTOTP = await UsersRaw.findActiveUsersTOTPEnable({ readPreference }).count();
statistics.totalUserEmail2fa = await UsersRaw.findActiveUsersEmail2faEnable({ readPreference }).count();
statistics.totalPinned = await MessagesRaw.findPinned({ readPreference }).count();
statistics.totalStarred = await MessagesRaw.findStarred({ readPreference }).count();
statistics.totalLinkInvitation = await Invites.find().count();
statistics.totalLinkInvitationUses = await Invites.countUses();
statistics.totalEmailInvitation = settings.get('Invitation_Email_Count');
statistics.totalE2ERooms = await RoomsRaw.findByE2E({ readPreference }).count();
statistics.logoChange = Object.keys(settings.get('Assets_logo')).includes('url');
statistics.homeTitleChanged = settings.get('Layout_Home_Title') !== 'Home';
statistics.showHomeButton = settings.get('Layout_Show_Home_Button');
statistics.totalEncryptedMessages = await MessagesRaw.countE2EEMessages({ readPreference });
statistics.totalManuallyAddedUsers = settings.get('Manual_Entry_User_Count');
await Promise.all(statsPms).catch(log);

@ -73,18 +73,8 @@ export default {
userLanguages: {},
teams: {
totalTeams: 0,
teamStats: [
{
teamId: '',
mainRoom: '',
totalRooms: 0,
totalMessages: 0,
totalPublicRooms: 0,
totalPrivateRooms: 0,
totalDefaultRooms: 0,
totalMembers: 0,
},
],
totalRoomsInsideTeams: 0,
totalDefaultRoomsInsideTeams: 0,
},
totalLivechatVisitors: 0,
totalLivechatAgents: 0,
@ -179,6 +169,7 @@ export default {
totalFailed: 0,
},
services: {},
importer: {},
settings: {},
integrations: {
totalIntegrations: 0,
@ -199,8 +190,7 @@ export default {
},
createdAt: new Date(),
showHomeButton: false,
homeTitle: '',
homeBody: '',
homeTitleChanged: false,
logoChange: false,
customCSS: 0,
customScript: 0,
@ -228,6 +218,13 @@ export default {
messageAuditLoad: 0,
dashboardCount: 0,
joinJitsiButton: 0,
totalLinkInvitation: 0,
roomsWithPinnedMessages: 0,
roomsWithStarredMessages: 0,
roomsInsideTeams: 0,
totalEncryptedMessages: 0,
totalLinkInvitationUses: 0,
totalManuallyAddedUsers: 0,
},
instances: [],
},

@ -103,18 +103,8 @@ export default {
userLanguages: {},
teams: {
totalTeams: 0,
teamStats: [
{
teamId: '',
mainRoom: '',
totalRooms: 0,
totalMessages: 0,
totalPublicRooms: 0,
totalPrivateRooms: 0,
totalDefaultRooms: 0,
totalMembers: 0,
},
],
totalRoomsInsideTeams: 0,
totalDefaultRoomsInsideTeams: 0,
},
totalLivechatVisitors: 0,
totalLivechatAgents: 0,
@ -209,6 +199,7 @@ export default {
totalFailed: 0,
},
services: {},
importer: {},
settings: {},
integrations: {
totalIntegrations: 0,
@ -229,8 +220,7 @@ export default {
},
createdAt: new Date(),
showHomeButton: false,
homeTitle: '',
homeBody: '',
homeTitleChanged: false,
logoChange: false,
customCSS: 0,
customScript: 0,
@ -258,6 +248,13 @@ export default {
messageAuditLoad: 0,
dashboardCount: 0,
joinJitsiButton: 0,
totalLinkInvitation: 0,
roomsWithPinnedMessages: 0,
roomsWithStarredMessages: 0,
roomsInsideTeams: 0,
totalEncryptedMessages: 0,
totalLinkInvitationUses: 0,
totalManuallyAddedUsers: 0,
},
instances: [],
},

@ -51,18 +51,8 @@ export default {
userLanguages: {},
teams: {
totalTeams: 0,
teamStats: [
{
teamId: '',
mainRoom: '',
totalRooms: 0,
totalMessages: 0,
totalPublicRooms: 0,
totalPrivateRooms: 0,
totalDefaultRooms: 0,
totalMembers: 0,
},
],
totalRoomsInsideTeams: 0,
totalDefaultRoomsInsideTeams: 0,
},
totalLivechatVisitors: 0,
totalLivechatAgents: 0,
@ -157,6 +147,7 @@ export default {
totalFailed: 0,
},
services: {},
importer: {},
settings: {},
integrations: {
totalIntegrations: 0,
@ -177,8 +168,7 @@ export default {
},
createdAt: new Date(),
showHomeButton: false,
homeTitle: '',
homeBody: '',
homeTitleChanged: false,
logoChange: false,
customCSS: 0,
customScript: 0,
@ -206,6 +196,13 @@ export default {
messageAuditLoad: 0,
dashboardCount: 0,
joinJitsiButton: 0,
totalLinkInvitation: 0,
roomsWithPinnedMessages: 0,
roomsWithStarredMessages: 0,
roomsInsideTeams: 0,
totalEncryptedMessages: 0,
totalLinkInvitationUses: 0,
totalManuallyAddedUsers: 0,
},
},
} as ComponentMeta<typeof UsageCard>;

@ -78,6 +78,9 @@ export function AddUser({ roles, onReload, ...props }) {
);
const saveAction = useEndpointAction('POST', 'users.create', values, t('User_created_successfully!'));
const eventStats = useEndpointAction('POST', 'statistics.telemetry', {
params: [{ eventName: 'updateCounter', settingsId: 'Manual_Entry_User_Count' }],
});
const handleSave = useMutableCallback(async () => {
Object.entries(values).forEach(([key, value]) => {
@ -94,6 +97,7 @@ export function AddUser({ roles, onReload, ...props }) {
const result = await saveAction();
if (result.success) {
eventStats();
goToUser(result.user._id);
onReload();
}

@ -1,5 +1,5 @@
import { IPaginationOptions, IQueryOptions, IRecordsWithTotal, ITeam, ITeamMember, ITeamStats, TEAM_TYPE } from '@rocket.chat/core-typings';
import { FilterQuery, FindOneOptions, WithoutProjection } from 'mongodb';
import { ITeam, IRecordsWithTotal, IPaginationOptions, IQueryOptions, ITeamMember, TEAM_TYPE } from '@rocket.chat/core-typings';
import type { IRoom, IUser, IRole } from '@rocket.chat/core-typings';
import { ICreateRoomParams } from './IRoomService';
@ -111,4 +111,5 @@ export interface ITeamService {
removeMemberFromTeams(userId: string, teamIds: Array<string>): Promise<void>;
removeAllMembersFromTeam(teamId: string): Promise<void>;
removeRolesFromMember(teamId: string, userId: string, roles: Array<IRole['_id']>): Promise<boolean>;
getStatistics(): Promise<ITeamStats>;
}

@ -8,7 +8,6 @@ import { addUserToRoom } from '../../../app/lib/server/functions/addUserToRoom';
import { removeUserFromRoom } from '../../../app/lib/server/functions/removeUserFromRoom';
import { getSubscribedRoomsForUserWithDetails } from '../../../app/lib/server/functions/getRoomsWithSingleOwner';
import type { InsertionModel } from '../../../app/models/server/raw/BaseRaw';
import { MessagesRaw } from '../../../app/models/server/raw/Messages';
import { RoomsRaw } from '../../../app/models/server/raw/Rooms';
import { SubscriptionsRaw } from '../../../app/models/server/raw/Subscriptions';
import { TeamRaw } from '../../../app/models/server/raw/Team';
@ -43,8 +42,6 @@ export class TeamService extends ServiceClassInternal implements ITeamService {
private TeamMembersModel: TeamMemberRaw;
private MessagesModel: MessagesRaw;
constructor(db: Db) {
super();
@ -55,7 +52,6 @@ export class TeamService extends ServiceClassInternal implements ITeamService {
});
this.TeamModel = new TeamRaw(db.collection('rocketchat_team'));
this.TeamMembersModel = new TeamMemberRaw(db.collection('rocketchat_team_member'));
this.MessagesModel = new MessagesRaw(db.collection('rocketchat_message'));
}
async create(uid: string, { team, room = { name: team.name, extraData: {} }, members, owner }: ITeamCreateParams): Promise<ITeam> {
@ -958,41 +954,11 @@ export class TeamService extends ServiceClassInternal implements ITeamService {
}
async getStatistics(): Promise<ITeamStats> {
const stats = {} as ITeamStats;
const teams = this.TeamModel.find({});
const teamsArray = await teams.toArray();
stats.totalTeams = await teams.count();
stats.teamStats = [];
for await (const team of teamsArray) {
// exclude the main room from the stats
const teamRooms = await this.RoomsModel.find({
teamId: team._id,
teamMain: { $exists: false },
}).toArray();
const roomIds = teamRooms.map((r) => r._id);
const [totalMessagesInTeam, defaultRooms, totalMembers] = await Promise.all([
this.MessagesModel.find({ rid: { $in: roomIds } }).count(),
this.RoomsModel.findDefaultRoomsForTeam(team._id).count(),
this.TeamMembersModel.findByTeamId(team._id).count(),
]);
const teamData = {
teamId: team._id,
mainRoom: team.roomId,
totalRooms: teamRooms.length,
totalMessages: totalMessagesInTeam,
totalPublicRooms: teamRooms.filter((r) => r.t === 'c').length,
totalPrivateRooms: teamRooms.filter((r) => r.t !== 'c').length,
totalDefaultRooms: defaultRooms,
totalMembers,
};
stats.teamStats.push(teamData);
}
return stats;
return {
totalTeams: await this.TeamModel.find({}).count(),
totalRoomsInsideTeams: await this.RoomsModel.findRoomsInsideTeams().count(),
totalDefaultRoomsInsideTeams: await this.RoomsModel.findRoomsInsideTeams(true).count(),
};
}
async autocomplete(uid: string, name: string): Promise<ITeamAutocompleteResult[]> {

@ -119,6 +119,7 @@ export interface IStats {
totalFailed: number | false;
};
services: Record<string, unknown>;
importer: Record<string, unknown>;
settings: ISettingStatisticsObject;
integrations: {
totalIntegrations: number;
@ -145,4 +146,22 @@ export interface IStats {
messageAuditLoad: number;
dashboardCount: number;
joinJitsiButton: number;
totalRoomsWithStarred: number;
totalRoomsWithPinned: number;
totalUserEmail2fa: number;
totalUserTOTP: number;
totalStarred: number;
totalPinned: number;
totalLinkInvitation: number;
totalEmailInvitation: number;
roomsWithPinnedMessages: number;
roomsWithStarredMessages: number;
totalE2ERooms: number;
logoChange: boolean;
homeTitleChanged: boolean;
roomsInsideTeams: number;
showHomeButton: boolean;
totalEncryptedMessages: number;
totalLinkInvitationUses: number;
totalManuallyAddedUsers: number;
}

@ -46,19 +46,10 @@ export interface IRecordsWithTotal<T> {
total: number;
}
export interface ITeamStatData {
teamId: string;
mainRoom: string;
totalRooms: number;
totalMessages: number;
totalPublicRooms: number;
totalPrivateRooms: number;
totalDefaultRooms: number;
totalMembers: number;
}
export interface ITeamStats {
totalTeams: number;
teamStats: Array<ITeamStatData>;
totalRoomsInsideTeams: number;
totalDefaultRoomsInsideTeams: number;
}
// TODO: move to service sdk package

Loading…
Cancel
Save