diff --git a/.meteor/packages b/.meteor/packages index 43602babb6b..16225b4b507 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -39,6 +39,7 @@ standard-minifier-js tracker rocketchat:action-links +rocketchat:analytics rocketchat:api rocketchat:assets rocketchat:authorization @@ -89,7 +90,6 @@ rocketchat:migrations rocketchat:oauth2-server-config rocketchat:oembed rocketchat:otr -rocketchat:piwik rocketchat:push-notifications rocketchat:reactions rocketchat:sandstorm diff --git a/.meteor/versions b/.meteor/versions index 45d6d4bc2f4..d6dec0cec84 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -120,6 +120,7 @@ reactive-var@1.0.11 reload@1.1.11 retry@1.0.9 rocketchat:action-links@0.0.1 +rocketchat:analytics@0.0.2 rocketchat:api@0.0.1 rocketchat:assets@0.0.1 rocketchat:authorization@0.0.1 @@ -175,7 +176,6 @@ rocketchat:oauth2-server@2.0.0 rocketchat:oauth2-server-config@1.0.0 rocketchat:oembed@0.0.1 rocketchat:otr@0.0.1 -rocketchat:piwik@0.0.1 rocketchat:push-notifications@0.0.1 rocketchat:reactions@0.0.1 rocketchat:sandstorm@0.0.1 diff --git a/packages/rocketchat-piwik/README.md b/packages/rocketchat-analytics/README.md similarity index 84% rename from packages/rocketchat-piwik/README.md rename to packages/rocketchat-analytics/README.md index d1e6a965dc8..4381e889f80 100644 --- a/packages/rocketchat-piwik/README.md +++ b/packages/rocketchat-analytics/README.md @@ -1,23 +1,29 @@ -# Piwik Analytics Tracking +# Analytics Tracking +## Google Analytics + +### Settings +* **Tracking ID**: Google Analytics tracking id found on analytics admin page - looks like UA-xxxxxxxx-x + +## Piwik Rocket.Chat supports adding Piwik url and site id to track the analytics of your server. Through this you will be able to see details analytics of per user, including how many messages a session they send via custom events in Piwik and how many channels they interact with. -## Piwik & Google Chrome +### Piwik & Google Chrome Google Chrome has a setting which sends a Do Not Track with each request and by default Piwik respects that and you have to manually disable that feature inside of Piwik. [Piwik has great documentation on how to disable this feature.](http://piwik.org/docs/privacy/#step-4-respect-donottrack-preference) -## Piwik Settings in Rocket.Chat -Settings -> Piwik - -### General +### Settings * **URL**: The url where your piwik is located. This is used for generating the tracking code and is required. Recommended format is: `//rocketchat.piwikpro.com/` * **Client ID**: The client id which this website is. This is a number without any decimals, example: `1` -### Features Enabled +## Settings in Rocket.Chat +Settings -> Analytics + +## Features Enabled * **Messages**: `true/false` determines whether to use custom events to track how many times a user does something with a message. This ranges from sending messages, editing messages, reacting to messages, pinning, starring, and etc. * **Rooms**: `true/false` determines whether to use custom events to track how many times a user does actions related to a room (channel, direct message, group). This ranges from creating, leaving, archiving, renaming, and etc. * **Users**: `true/false` determines whether to use custom events to track how many times a user does actions related to users. This ranges from resetting passwords, creating new users, updating profile pictures, etc. diff --git a/packages/rocketchat-analytics/client/loadScript.js b/packages/rocketchat-analytics/client/loadScript.js new file mode 100644 index 00000000000..a22e8afe317 --- /dev/null +++ b/packages/rocketchat-analytics/client/loadScript.js @@ -0,0 +1,44 @@ +Template.body.onRendered(() => { + Tracker.autorun((c) => { + const piwikUrl = RocketChat.settings.get('PiwikAnalytics_enabled') && RocketChat.settings.get('PiwikAnalytics_url'); + const piwikSiteId = piwikUrl && RocketChat.settings.get('PiwikAnalytics_siteId'); + const googleId = RocketChat.settings.get('GoogleAnalytics_enabled') && RocketChat.settings.get('GoogleAnalytics_ID'); + if (piwikSiteId || googleId) { + c.stop(); + + if (piwikSiteId) { + window._paq = window._paq || []; + if (Meteor.userId()) { + window._paq.push(['setUserId', Meteor.userId()]); + } + + window._paq.push(['trackPageView']); + window._paq.push(['enableLinkTracking']); + (() => { + window._paq.push(['setTrackerUrl', piwikUrl + 'piwik.php']); + window._paq.push(['setSiteId', Number.parseInt(piwikSiteId)]); + const d = document; + const g = d.createElement('script'); + const s = d.getElementsByTagName('script')[0]; + g.type = 'text/javascript'; + g.async = true; + g.defer = true; + g.src = piwikUrl + 'piwik.js'; + s.parentNode.insertBefore(g, s); + })(); + } + + if (googleId) { + /*eslint-disable */ + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); + + ga('create', googleId, 'auto'); + ga('send', 'pageview'); + /*eslint-enable */ + } + } + }); +}); diff --git a/packages/rocketchat-analytics/client/trackEvents.js b/packages/rocketchat-analytics/client/trackEvents.js new file mode 100644 index 00000000000..c672e8bb73d --- /dev/null +++ b/packages/rocketchat-analytics/client/trackEvents.js @@ -0,0 +1,137 @@ +function trackEvent(category, action, label) { + if (window._paq) { + window._paq.push(['trackEvent', category, action, label]); + } + if (window.ga) { + window.ga('send', 'event', category, action, label); + } +} + +if (!window._paq || window.ga) { + //Trigger the trackPageView manually as the page views don't seem to be tracked + FlowRouter.triggers.enter([(route) => { + if (window._paq) { + const http = location.protocol; + const slashes = http.concat('//'); + const host = slashes.concat(window.location.hostname); + window._paq.push(['setCustomUrl', host + route.path]); + window._paq.push(['trackPageView']); + } + if (window.ga) { + window.ga('send', 'pageview', route.path); + } + }]); + + //Login page has manual switches + RocketChat.callbacks.add('loginPageStateChange', (state) => { + trackEvent('Navigation', 'Login Page State Change', state); + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-login-state-change'); + + //Messsages + RocketChat.callbacks.add('afterSaveMessage', (message) => { + if ((window._paq || window.ga) && RocketChat.settings.get('Analytics_features_messages')) { + const room = ChatRoom.findOne({ _id: message.rid }); + trackEvent('Message', 'Send', room.name + ' (' + room._id + ')'); + } + }, 2000, 'trackEvents'); + + //Rooms + RocketChat.callbacks.add('afterCreateChannel', (owner, room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Create', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-after-create-channel'); + + RocketChat.callbacks.add('roomNameChanged', (room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Changed Name', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-room-name-changed'); + + RocketChat.callbacks.add('roomTopicChanged', (room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Changed Topic', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-room-topic-changed'); + + RocketChat.callbacks.add('roomTypeChanged', (room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Changed Room Type', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-room-type-changed'); + + RocketChat.callbacks.add('archiveRoom', (room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Archived', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-archive-room'); + + RocketChat.callbacks.add('unarchiveRoom', (room) => { + if (RocketChat.settings.get('Analytics_features_rooms')) { + trackEvent('Room', 'Unarchived', room.name + ' (' + room._id + ')'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-unarchive-room'); + + //Users + //Track logins and associate user ids with piwik + (() => { + let oldUserId = null; + + Meteor.autorun(() => { + const newUserId = Meteor.userId(); + if (oldUserId === null && newUserId) { + if (window._paq && RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Login', newUserId); + window._paq.push(['setUserId', newUserId]); + } + } else if (newUserId === null && oldUserId) { + if (window._paq && RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Logout', oldUserId); + } + } + oldUserId = Meteor.userId(); + }); + })(); + + RocketChat.callbacks.add('userRegistered', () => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Registered'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-resitered'); + + RocketChat.callbacks.add('usernameSet', () => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Username Set'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'piweik-username-set'); + + RocketChat.callbacks.add('userPasswordReset', () => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Reset Password'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-password-reset'); + + RocketChat.callbacks.add('userConfirmationEmailRequested', () => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Confirmation Email Requested'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-confirmation-email-requested'); + + RocketChat.callbacks.add('userForgotPasswordEmailRequested', () => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Forgot Password Email Requested'); + } + }, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-forgot-password-email-requested'); + + RocketChat.callbacks.add('userStatusManuallySet', (status) => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Status Manually Changed', status); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-user-status-manually-set'); + + RocketChat.callbacks.add('userAvatarSet', (service) => { + if (RocketChat.settings.get('Analytics_features_users')) { + trackEvent('User', 'Avatar Changed', service); + } + }, RocketChat.callbacks.priority.MEDIUM, 'analytics-user-avatar-set'); +} diff --git a/packages/rocketchat-piwik/package.js b/packages/rocketchat-analytics/package.js similarity index 80% rename from packages/rocketchat-piwik/package.js rename to packages/rocketchat-analytics/package.js index 821e1f6e1d6..913a11aa748 100644 --- a/packages/rocketchat-piwik/package.js +++ b/packages/rocketchat-analytics/package.js @@ -1,7 +1,7 @@ Package.describe({ - name: 'rocketchat:piwik', - version: '0.0.1', - summary: 'Piwik integeration for Rocket.Chat', + name: 'rocketchat:analytics', + version: '0.0.2', + summary: 'Analytics integeration for Rocket.Chat', git: '' }); diff --git a/packages/rocketchat-analytics/server/settings.js b/packages/rocketchat-analytics/server/settings.js new file mode 100644 index 00000000000..e639cf8eafe --- /dev/null +++ b/packages/rocketchat-analytics/server/settings.js @@ -0,0 +1,59 @@ +RocketChat.settings.addGroup('Analytics', function addSettings() { + this.section('Piwik', function() { + const enableQuery = {_id: 'PiwikAnalytics_enabled', value: true}; + this.add('PiwikAnalytics_enabled', false, { + type: 'boolean', + public: true, + i18nLabel: 'Enable' + }); + this.add('PiwikAnalytics_url', '', { + type: 'string', + public: true, + i18nLabel: 'URL', + enableQuery + }); + this.add('PiwikAnalytics_siteId', '', { + type: 'string', + public: true, + i18nLabel: 'Client_ID', + enableQuery + }); + }); + + this.section('Analytics_Google', function() { + const enableQuery = {_id: 'GoogleAnalytics_enabled', value: true}; + this.add('GoogleAnalytics_enabled', false, { + type: 'boolean', + public: true, + i18nLabel: 'Enable' + }); + + this.add('GoogleAnalytics_ID', '', { + type: 'string', + public: true, + i18nLabel: 'Analytics_Google_id', + enableQuery + }); + }); + + this.section('Analytics_features_enabled', function addFeaturesEnabledSettings() { + this.add('Analytics_features_messages', true, { + type: 'boolean', + public: true, + i18nLabel: 'Messages', + i18nDescription: 'Analytics_features_messages_Description' + }); + this.add('Analytics_features_rooms', true, { + type: 'boolean', + public: true, + i18nLabel: 'Rooms', + i18nDescription: 'Analytics_features_rooms_Description' + }); + this.add('Analytics_features_users', true, { + type: 'boolean', + public: true, + i18nLabel: 'Users', + i18nDescription: 'Analytics_features_users_Description' + }); + }); +}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 53be37b2d70..db92fe7df44 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -154,6 +154,8 @@ "Analytics_features_messages_Description": "Tracks custom events related to actions a user does on messages.", "Analytics_features_rooms_Description": "Tracks custom events related to actions on a channel or group (create, leave, delete).", "Analytics_features_users_Description": "Tracks custom events related to actions related to users (password reset times, profile picture change, etc).", + "Analytics_Google": "Google Analytics", + "Analytics_Google_id": "Tracking ID", "and": "and", "And_more": "And __length__ more", "Animals_and_Nature": "Animals & Nature", diff --git a/packages/rocketchat-ldap/server/sync.js b/packages/rocketchat-ldap/server/sync.js index 24456f7ac9a..8e75229e584 100644 --- a/packages/rocketchat-ldap/server/sync.js +++ b/packages/rocketchat-ldap/server/sync.js @@ -74,7 +74,7 @@ getDataToSyncUserData = function getDataToSyncUserData(ldapUser, user) { switch (userField) { case 'email': - if (_.isObject(ldapUser.object[ldapField] === 'object')) { + if (_.isObject(ldapUser.object[ldapField])) { _.map(ldapUser.object[ldapField], function(item) { emailList.push({ address: item, verified: true }); }); diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 652f2de2b5c..c59e21755f7 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -110,6 +110,9 @@ Package.onUse(function(api) { api.addFiles('server/models/Uploads.coffee', 'server'); api.addFiles('server/models/Users.coffee', 'server'); + api.addFiles('server/oauth/oauth.js', 'server'); + api.addFiles('server/oauth/google.js', 'server'); + api.addFiles('server/startup/statsTracker.js', 'server'); // CACHE diff --git a/packages/rocketchat-lib/server/methods/restartServer.js b/packages/rocketchat-lib/server/methods/restartServer.js index 63da91d7776..100cf528155 100644 --- a/packages/rocketchat-lib/server/methods/restartServer.js +++ b/packages/rocketchat-lib/server/methods/restartServer.js @@ -10,7 +10,7 @@ Meteor.methods({ Meteor.setTimeout(() => { Meteor.setTimeout(() => { - console.warn("process.exit() timed out, aborting..."); + console.warn('Call to process.exit() timed out, aborting.'); process.abort(); } , 1000); diff --git a/packages/rocketchat-lib/server/oauth/google.js b/packages/rocketchat-lib/server/oauth/google.js new file mode 100644 index 00000000000..a2771fce8d1 --- /dev/null +++ b/packages/rocketchat-lib/server/oauth/google.js @@ -0,0 +1,60 @@ +/* globals Google */ + +function getIdentity(accessToken) { + try { + return HTTP.get( + 'https://www.googleapis.com/oauth2/v1/userinfo', + {params: {access_token: accessToken}}).data; + } catch (err) { + throw _.extend(new Error('Failed to fetch identity from Google. ' + err.message), {response: err.response}); + } +} + +function getScopes(accessToken) { + try { + return HTTP.get( + 'https://www.googleapis.com/oauth2/v1/tokeninfo', + {params: {access_token: accessToken}}).data.scope.split(' '); + } catch (err) { + throw _.extend(new Error('Failed to fetch tokeninfo from Google. ' + err.message), {response: err.response}); + } +} + + +RocketChat.registerAccessTokenService('google', function(options) { + check(options, { + accessToken: String, + idToken: String, + expiresAt: Match.Integer, + scope: Match.Maybe(String), + identity: Match.Maybe(Object) + }); + + const identity = options.identity || getIdentity(options.accessToken); + + const serviceData = { + accessToken: options.accessToken, + idToken: options.idToken, + expiresAt: (+new Date) + (1000 * parseInt(options.expiresIn, 10)), + scope: options.scopes || getScopes(options.accessToken) + }; + + const fields = _.pick(identity, Google.whitelistedFields); + _.extend(serviceData, fields); + + // only set the token in serviceData if it's there. this ensures + // that we don't lose old ones (since we only get this on the first + // log in attempt) + if (options.refreshToken) { + serviceData.refreshToken = options.refreshToken; + } + + return { + serviceData: serviceData, + options: { + profile: { + name: identity.name + } + } + }; +}); diff --git a/packages/rocketchat-lib/server/oauth/oauth.js b/packages/rocketchat-lib/server/oauth/oauth.js new file mode 100644 index 00000000000..3a72ad03377 --- /dev/null +++ b/packages/rocketchat-lib/server/oauth/oauth.js @@ -0,0 +1,52 @@ +const AccessTokenServices = {}; + +RocketChat.registerAccessTokenService = function(serviceName, handleAccessTokenRequest) { + AccessTokenServices[serviceName] = { + serviceName: serviceName, + handleAccessTokenRequest: handleAccessTokenRequest + }; +}; + +// Listen to calls to `login` with an oauth option set. This is where +// users actually get logged in to meteor via oauth. +Accounts.registerLoginHandler(function(options) { + if (!options.accessToken) { + return undefined; // don't handle + } + + check(options.oauth, { + serviceName: String + }); + + const service = AccessTokenServices[options.serviceName]; + + // Skip everything if there's no service set by the oauth middleware + if (!service) { + throw new Error(`Unexpected AccessToken service ${options.serviceName}`); + } + + // Make sure we're configured + if (!ServiceConfiguration.configurations.findOne({service: service.serviceName})) { + throw new ServiceConfiguration.ConfigError(); + } + + if (!_.contains(Accounts.oauth.serviceNames(), service.serviceName)) { + // serviceName was not found in the registered services list. + // This could happen because the service never registered itself or + // unregisterService was called on it. + return { + type: 'oauth', + error: new Meteor.Error( + Accounts.LoginCancelledError.numericError, + `No registered oauth service found for: ${service.serviceName}` + ) + }; + } + + const oauthResult = service.handleAccessTokenRequest(options); + + return Accounts.updateOrCreateUserFromExternalService(service.serviceName, oauthResult.serviceData, oauthResult.options); +}); + + + diff --git a/packages/rocketchat-piwik/client/loadScript.js b/packages/rocketchat-piwik/client/loadScript.js deleted file mode 100644 index 5c39be4e24b..00000000000 --- a/packages/rocketchat-piwik/client/loadScript.js +++ /dev/null @@ -1,29 +0,0 @@ -Template.body.onRendered(() => { - Tracker.autorun((c) => { - const url = RocketChat.settings.get('PiwikAnalytics_url'); - const siteId = RocketChat.settings.get('PiwikAnalytics_siteId'); - - if (Match.test(url, String) && url.trim() !== '' && Match.test(siteId, String) && siteId.trim() !== '') { - c.stop(); - window._paq = window._paq || []; - if (Meteor.userId()) { - window._paq.push(['setUserId', Meteor.userId()]); - } - - window._paq.push(['trackPageView']); - window._paq.push(['enableLinkTracking']); - (() => { - window._paq.push(['setTrackerUrl', url + 'piwik.php']); - window._paq.push(['setSiteId', Number.parseInt(siteId)]); - const d = document; - const g = d.createElement('script'); - const s = d.getElementsByTagName('script')[0]; - g.type = 'text/javascript'; - g.async = true; - g.defer = true; - g.src = url + 'piwik.js'; - s.parentNode.insertBefore(g, s); - })(); - } - }); -}); diff --git a/packages/rocketchat-piwik/client/trackEvents.js b/packages/rocketchat-piwik/client/trackEvents.js deleted file mode 100644 index cd66c66251c..00000000000 --- a/packages/rocketchat-piwik/client/trackEvents.js +++ /dev/null @@ -1,126 +0,0 @@ -//Trigger the trackPageView manually as the page views don't seem to be tracked -FlowRouter.triggers.enter([(route) => { - if (window._paq) { - const http = location.protocol; - const slashes = http.concat('//'); - const host = slashes.concat(window.location.hostname); - - window._paq.push(['setCustomUrl', host + route.path]); - window._paq.push(['trackPageView']); - } -}]); - -//Login page has manual switches -RocketChat.callbacks.add('loginPageStateChange', (state) => { - if (window._paq) { - window._paq.push(['trackEvent', 'Navigation', 'Login Page State Change', state]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-login-state-change'); - -//Messsages -RocketChat.callbacks.add('afterSaveMessage', (message) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_messages')) { - const room = ChatRoom.findOne({ _id: message.rid }); - window._paq.push(['trackEvent', 'Message', 'Send', room.name + ' (' + room._id + ')' ]); - } -}, 2000, 'trackEvents'); - -//Rooms -RocketChat.callbacks.add('afterCreateChannel', (owner, room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Create', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-after-create-channel'); - -RocketChat.callbacks.add('roomNameChanged', (room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Changed Name', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-room-name-changed'); - -RocketChat.callbacks.add('roomTopicChanged', (room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Changed Topic', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-room-topic-changed'); - -RocketChat.callbacks.add('roomTypeChanged', (room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Changed Room Type', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-room-type-changed'); - -RocketChat.callbacks.add('archiveRoom', (room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Archived', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-archive-room'); - -RocketChat.callbacks.add('unarchiveRoom', (room) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_rooms')) { - window._paq.push(['trackEvent', 'Room', 'Unarchived', room.name + ' (' + room._id + ')' ]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-unarchive-room'); - -//Users -//Track logins and associate user ids with piwik -(() => { - let oldUserId = null; - - Meteor.autorun(() => { - const newUserId = Meteor.userId(); - if (oldUserId === null && newUserId) { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Login', newUserId ]); - window._paq.push(['setUserId', newUserId]); - } - } else if (newUserId === null && oldUserId) { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Logout', oldUserId ]); - } - } - oldUserId = Meteor.userId(); - }); -})(); - -RocketChat.callbacks.add('userRegistered', () => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Registered']); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-resitered'); - -RocketChat.callbacks.add('usernameSet', () => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Username Set']); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piweik-username-set'); - -RocketChat.callbacks.add('userPasswordReset', () => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Reset Password']); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-password-reset'); - -RocketChat.callbacks.add('userConfirmationEmailRequested', () => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Confirmation Email Requested']); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-confirmation-email-requested'); - -RocketChat.callbacks.add('userForgotPasswordEmailRequested', () => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Forgot Password Email Requested']); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-forgot-password-email-requested'); - -RocketChat.callbacks.add('userStatusManuallySet', (status) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Status Manually Changed', status]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-status-manually-set'); - -RocketChat.callbacks.add('userAvatarSet', (service) => { - if (window._paq && RocketChat.settings.get('PiwikAnalytics_features_users')) { - window._paq.push(['trackEvent', 'User', 'Avatar Changed', service]); - } -}, RocketChat.callbacks.priority.MEDIUM, 'piwik-user-avatar-set'); diff --git a/packages/rocketchat-piwik/server/settings.js b/packages/rocketchat-piwik/server/settings.js deleted file mode 100644 index eb6e96f9655..00000000000 --- a/packages/rocketchat-piwik/server/settings.js +++ /dev/null @@ -1,33 +0,0 @@ -RocketChat.settings.addGroup('Piwik', function addSettings() { - this.add('PiwikAnalytics_url', '', { - type: 'string', - public: true, - i18nLabel: 'URL' - }); - this.add('PiwikAnalytics_siteId', '', { - type: 'string', - public: true, - i18nLabel: 'Client_ID' - }); - - this.section('Analytics_features_enabled', function addFeaturesEnabledSettings() { - this.add('PiwikAnalytics_features_messages', true, { - type: 'boolean', - public: true, - i18nLabel: 'Messages', - i18nDescription: 'Analytics_features_messages_Description' - }); - this.add('PiwikAnalytics_features_rooms', true, { - type: 'boolean', - public: true, - i18nLabel: 'Rooms', - i18nDescription: 'Analytics_features_rooms_Description' - }); - this.add('PiwikAnalytics_features_users', true, { - type: 'boolean', - public: true, - i18nLabel: 'Users', - i18nDescription: 'Analytics_features_users_Description' - }); - }); -}); diff --git a/packages/rocketchat-videobridge/client/views/videoFlexTab.js b/packages/rocketchat-videobridge/client/views/videoFlexTab.js index af5294e8a5a..fd5642cc686 100644 --- a/packages/rocketchat-videobridge/client/views/videoFlexTab.js +++ b/packages/rocketchat-videobridge/client/views/videoFlexTab.js @@ -3,7 +3,11 @@ Template.videoFlexTab.helpers({ openInNewWindow() { - return RocketChat.settings.get('Jitsi_Open_New_Window'); + if (Meteor.isCordova) { + return true; + } else { + return RocketChat.settings.get('Jitsi_Open_New_Window'); + } } }); @@ -61,21 +65,30 @@ Template.videoFlexTab.onRendered(function() { RocketChat.TabBar.updateButton('video', { class: 'red' }); - if (RocketChat.settings.get('Jitsi_Open_New_Window')) { + if (RocketChat.settings.get('Jitsi_Open_New_Window') || Meteor.isCordova) { Meteor.call('jitsi:updateTimeout', roomId); timeOut = Meteor.setInterval(() => Meteor.call('jitsi:updateTimeout', roomId), 10*1000); + var newWindow = null; + if (Meteor.isCordova) { + newWindow = window.open((noSsl ? 'http://' : 'https://') + domain + '/' + jitsiRoom, '_system'); + closePanel(); + clearInterval(timeOut); + } else { + newWindow = window.open((noSsl ? 'http://' : 'https://') + domain + '/' + jitsiRoom, jitsiRoom); + const closeInterval = setInterval(() => { + if (newWindow.closed !== false) { + closePanel(); + clearInterval(closeInterval); + clearInterval(timeOut); + } + }, 300); + } + if (newWindow) { + newWindow.focus(); + } - const newWindow = window.open((noSsl ? 'http://' : 'https://') + domain + '/' + jitsiRoom, jitsiRoom); - newWindow.focus(); - const closeInterval = setInterval(() => { - if (newWindow.closed !== false) { - closePanel(); - clearInterval(closeInterval); - clearInterval(timeOut); - } - }, 300); // Lets make sure its loaded before we try to show it. } else if (typeof JitsiMeetExternalAPI !== 'undefined') { @@ -114,3 +127,4 @@ Template.videoFlexTab.onRendered(function() { } }); }); + diff --git a/server/startup/migrations/v090.js b/server/startup/migrations/v090.js new file mode 100644 index 00000000000..df469f86155 --- /dev/null +++ b/server/startup/migrations/v090.js @@ -0,0 +1,12 @@ +RocketChat.Migrations.add({ + version: 90, + up() { + RocketChat.models.Settings.remove({ _id: 'Piwik', type: 'group' }); + + const settings = RocketChat.models.Settings.find({$or: [{_id: 'PiwikAnalytics_url', value: {$ne: null}}, {_id: 'PiwikAnalytics_siteId', value: {$ne: null}}]}).fetch(); + + if (settings && settings.length === 2) { + RocketChat.models.Settings.upsert({_id: 'PiwikAnalytics_enabled'}, {$set: {value: true}}); + } + } +});