diff --git a/api/post.go b/api/post.go
index c533ad656c..a33b6ebf08 100644
--- a/api/post.go
+++ b/api/post.go
@@ -697,55 +697,60 @@ func sendNotifications(c *Context, post *model.Post, team *model.Team, channel *
sessions := result.Data.([]*model.Session)
alreadySeen := make(map[string]string)
- for _, session := range sessions {
- if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" &&
- (strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) {
- alreadySeen[session.DeviceId] = session.DeviceId
+ pushServer := *utils.Cfg.EmailSettings.PushNotificationServer
+ if pushServer == model.MHPNS && (!utils.IsLicensed || !*utils.License.Features.MHPNS) {
+ l4g.Warn(utils.T("api.post.send_notifications_and_forget.push_notification.mhpnsWarn"))
+ } else {
+ for _, session := range sessions {
+ if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" &&
+ (strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")) {
+ alreadySeen[session.DeviceId] = session.DeviceId
- msg := model.PushNotification{}
- if badge := <-Srv.Store.User().GetUnreadCount(id); badge.Err != nil {
- msg.Badge = 1
- l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), id, badge.Err)
- } else {
- msg.Badge = int(badge.Data.(int64))
- }
- msg.ServerId = utils.CfgDiagnosticId
- msg.ChannelId = channel.Id
- msg.ChannelName = channel.Name
-
- if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") {
- msg.Platform = model.PUSH_NOTIFY_APPLE
- msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":")
- } else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") {
- msg.Platform = model.PUSH_NOTIFY_ANDROID
- msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")
- }
-
- if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
+ msg := model.PushNotification{}
+ if badge := <-Srv.Store.User().GetUnreadCount(id); badge.Err != nil {
+ msg.Badge = 1
+ l4g.Error(utils.T("store.sql_user.get_unread_count.app_error"), id, badge.Err)
} else {
- msg.Message = "@" + senderName + " @ " + channelName + ": " + model.ClearMentionTags(post.Message)
+ msg.Badge = int(badge.Data.(int64))
}
- } else {
- if channel.Type == model.CHANNEL_DIRECT {
- msg.Category = model.CATEGORY_DM
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
+ msg.ServerId = utils.CfgDiagnosticId
+ msg.ChannelId = channel.Id
+ msg.ChannelName = channel.Name
+
+ if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":") {
+ msg.Platform = model.PUSH_NOTIFY_APPLE
+ msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_APPLE+":")
+ } else if strings.HasPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":") {
+ msg.Platform = model.PUSH_NOTIFY_ANDROID
+ msg.DeviceId = strings.TrimPrefix(session.DeviceId, model.PUSH_NOTIFY_ANDROID+":")
+ }
+
+ if *utils.Cfg.EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION {
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = "@" + senderName + ": " + model.ClearMentionTags(post.Message)
+ } else {
+ msg.Message = "@" + senderName + " @ " + channelName + ": " + model.ClearMentionTags(post.Message)
+ }
} else {
- msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
+ if channel.Type == model.CHANNEL_DIRECT {
+ msg.Category = model.CATEGORY_DM
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
+ } else {
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
+ }
}
- }
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- httpClient := &http.Client{Transport: tr}
- request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ httpClient := &http.Client{Transport: tr}
+ request, _ := http.NewRequest("POST", pushServer+model.API_URL_SUFFIX_V1+"/send_push", strings.NewReader(msg.ToJson()))
- l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
- if _, err := httpClient.Do(request); err != nil {
- l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), id, err)
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
+ if _, err := httpClient.Do(request); err != nil {
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), id, err)
+ }
}
}
}
diff --git a/model/license.go b/model/license.go
index 0cea67c3d1..bc72ff9adc 100644
--- a/model/license.go
+++ b/model/license.go
@@ -32,15 +32,22 @@ type Customer struct {
}
type Features struct {
- Users *int `json:"users"`
- LDAP *bool `json:"ldap"`
- MFA *bool `json:"mfa"`
- GoogleSSO *bool `json:"google_sso"`
- Compliance *bool `json:"compliance"`
- CustomBrand *bool `json:"custom_brand"`
+ Users *int `json:"users"`
+ LDAP *bool `json:"ldap"`
+ MFA *bool `json:"mfa"`
+ GoogleSSO *bool `json:"google_sso"`
+ Compliance *bool `json:"compliance"`
+ CustomBrand *bool `json:"custom_brand"`
+ MHPNS *bool `json:"mhpns"`
+ FutureFeatures *bool `json:"future_features"`
}
func (f *Features) SetDefaults() {
+ if f.FutureFeatures == nil {
+ f.FutureFeatures = new(bool)
+ *f.FutureFeatures = true
+ }
+
if f.Users == nil {
f.Users = new(int)
*f.Users = 0
@@ -48,27 +55,32 @@ func (f *Features) SetDefaults() {
if f.LDAP == nil {
f.LDAP = new(bool)
- *f.LDAP = true
+ *f.LDAP = *f.FutureFeatures
}
if f.MFA == nil {
f.MFA = new(bool)
- *f.MFA = true
+ *f.MFA = *f.FutureFeatures
}
if f.GoogleSSO == nil {
f.GoogleSSO = new(bool)
- *f.GoogleSSO = true
+ *f.GoogleSSO = *f.FutureFeatures
}
if f.Compliance == nil {
f.Compliance = new(bool)
- *f.Compliance = true
+ *f.Compliance = *f.FutureFeatures
}
if f.CustomBrand == nil {
f.CustomBrand = new(bool)
- *f.CustomBrand = true
+ *f.CustomBrand = *f.FutureFeatures
+ }
+
+ if f.MHPNS == nil {
+ f.MHPNS = new(bool)
+ *f.MHPNS = *f.FutureFeatures
}
}
diff --git a/model/push_notification.go b/model/push_notification.go
index 9196a44dd8..666dd8f7d4 100644
--- a/model/push_notification.go
+++ b/model/push_notification.go
@@ -13,6 +13,8 @@ const (
PUSH_NOTIFY_ANDROID = "android"
CATEGORY_DM = "DIRECT_MESSAGE"
+
+ MHPNS = "https://push.mattermost.com"
)
type PushNotification struct {
diff --git a/utils/license.go b/utils/license.go
index d3654932f8..6905bee4fc 100644
--- a/utils/license.go
+++ b/utils/license.go
@@ -124,6 +124,7 @@ func getClientLicense(l *model.License) map[string]string {
props["GoogleSSO"] = strconv.FormatBool(*l.Features.GoogleSSO)
props["Compliance"] = strconv.FormatBool(*l.Features.Compliance)
props["CustomBrand"] = strconv.FormatBool(*l.Features.CustomBrand)
+ props["MHPNS"] = strconv.FormatBool(*l.Features.MHPNS)
props["IssuedAt"] = strconv.FormatInt(l.IssuedAt, 10)
props["StartsAt"] = strconv.FormatInt(l.StartsAt, 10)
props["ExpiresAt"] = strconv.FormatInt(l.ExpiresAt, 10)
diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx
index 9f9e85de11..da406e6476 100644
--- a/webapp/components/admin_console/admin_sidebar.jsx
+++ b/webapp/components/admin_console/admin_sidebar.jsx
@@ -184,35 +184,39 @@ export default class AdminSidebar extends React.Component {
let licenseSettings;
if (global.window.mm_config.BuildEnterpriseReady === 'true') {
if (global.window.mm_license.IsLicensed === 'true') {
- ldapSettings = (
-
-
-
-
-
- );
+ if (global.window.mm_license.LDAP === 'true') {
+ ldapSettings = (
+
+
+
+
+
+ );
+ }
- complianceSettings = (
-
-
-
-
-
- );
+ if (global.window.mm_license.Compliance === 'true') {
+ complianceSettings = (
+
+
+
+
+
+ );
+ }
}
licenseSettings = (
diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx
index 1fa75ead9b..7e8ad616f4 100644
--- a/webapp/components/admin_console/email_settings.jsx
+++ b/webapp/components/admin_console/email_settings.jsx
@@ -10,6 +10,9 @@ import ConnectionSecurityDropdownSetting from './connection_security_dropdown_se
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+import * as Utils from 'utils/utils.jsx';
+import Constants from 'utils/constants.jsx';
+
var holders = defineMessages({
notificationDisplayExample: {
id: 'admin.email.notificationDisplayExample',
@@ -43,18 +46,6 @@ var holders = defineMessages({
id: 'admin.email.passwordSaltExample',
defaultMessage: 'Ex "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9Yo"'
},
- pushServerEx: {
- id: 'admin.email.pushServerEx',
- defaultMessage: 'E.g.: "http://push-test.mattermost.com"'
- },
- genericPush: {
- id: 'admin.email.genericPushNotification',
- defaultMessage: 'Send generic description with user and channel names'
- },
- fullPush: {
- id: 'admin.email.fullPushNotification',
- defaultMessage: 'Send full message snippet'
- },
testing: {
id: 'admin.email.testing',
defaultMessage: 'Testing...'
@@ -77,6 +68,29 @@ class EmailSettings extends React.Component {
this.buildConfig = this.buildConfig.bind(this);
this.handleGenerateInvite = this.handleGenerateInvite.bind(this);
this.handleGenerateReset = this.handleGenerateReset.bind(this);
+ this.handleSendPushNotificationsChange = this.handleSendPushNotificationsChange.bind(this);
+ this.handlePushServerChange = this.handlePushServerChange.bind(this);
+ this.handleAgreeChange = this.handleAgreeChange.bind(this);
+
+ let sendNotificationValue;
+ let agree = false;
+ if (!props.config.EmailSettings.SendPushNotifications) {
+ sendNotificationValue = 'off';
+ } else if (props.config.EmailSettings.PushNotificationServer === Constants.MHPNS && global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') {
+ sendNotificationValue = 'mhpns';
+ agree = true;
+ } else if (props.config.EmailSettings.PushNotificationServer === Constants.MTPNS) {
+ sendNotificationValue = 'mtpns';
+ } else {
+ sendNotificationValue = 'self';
+ }
+
+ let pushNotificationServer = this.props.config.EmailSettings.PushNotificationServer;
+ if (sendNotificationValue === 'mtpns') {
+ pushNotificationServer = Constants.MTPNS;
+ } else if (sendNotificationValue === 'mhpns') {
+ pushNotificationServer = Constants.MHPNS;
+ }
this.state = {
sendEmailNotifications: this.props.config.EmailSettings.SendEmailNotifications,
@@ -86,12 +100,15 @@ class EmailSettings extends React.Component {
emailSuccess: null,
emailFail: null,
pushNotificationContents: this.props.config.EmailSettings.PushNotificationContents,
- connectionSecurity: this.props.config.EmailSettings.ConnectionSecurity
+ connectionSecurity: this.props.config.EmailSettings.ConnectionSecurity,
+ sendNotificationValue,
+ pushNotificationServer,
+ agree
};
}
handleChange(action) {
- var s = {saveNeeded: true, serverError: this.state.serverError};
+ const s = {saveNeeded: true};
if (action === 'sendEmailNotifications_true') {
s.sendEmailNotifications = true;
@@ -113,18 +130,15 @@ class EmailSettings extends React.Component {
}
buildConfig() {
- var config = this.props.config;
+ const config = this.props.config;
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
config.EmailSettings.EnableSignInWithEmail = ReactDOM.findDOMNode(this.refs.allowSignInWithEmail).checked;
config.EmailSettings.EnableSignInWithUsername = ReactDOM.findDOMNode(this.refs.allowSignInWithUsername).checked;
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
- config.EmailSettings.SendPushNotifications = ReactDOM.findDOMNode(this.refs.sendPushNotifications).checked;
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
config.EmailSettings.FeedbackName = ReactDOM.findDOMNode(this.refs.feedbackName).value.trim();
config.EmailSettings.FeedbackEmail = ReactDOM.findDOMNode(this.refs.feedbackEmail).value.trim();
config.EmailSettings.SMTPServer = ReactDOM.findDOMNode(this.refs.SMTPServer).value.trim();
- config.EmailSettings.PushNotificationServer = ReactDOM.findDOMNode(this.refs.PushNotificationServer).value.trim();
- config.EmailSettings.PushNotificationContents = ReactDOM.findDOMNode(this.refs.PushNotificationContents).value;
config.EmailSettings.SMTPPort = ReactDOM.findDOMNode(this.refs.SMTPPort).value.trim();
config.EmailSettings.SMTPUsername = ReactDOM.findDOMNode(this.refs.SMTPUsername).value.trim();
config.EmailSettings.SMTPPassword = ReactDOM.findDOMNode(this.refs.SMTPPassword).value.trim();
@@ -142,9 +156,43 @@ class EmailSettings extends React.Component {
ReactDOM.findDOMNode(this.refs.PasswordResetSalt).value = config.EmailSettings.PasswordResetSalt;
}
+ const sendPushNotifications = this.refs.sendPushNotifications.value;
+ if (sendPushNotifications === 'off') {
+ config.EmailSettings.SendPushNotifications = false;
+ } else {
+ config.EmailSettings.SendPushNotifications = true;
+ }
+
+ if (this.refs.PushNotificationServer) {
+ config.EmailSettings.PushNotificationServer = this.refs.PushNotificationServer.value.trim();
+ }
+
+ if (this.refs.PushNotificationContents) {
+ config.EmailSettings.PushNotificationContents = this.refs.PushNotificationContents.value;
+ }
+
return config;
}
+ handleSendPushNotificationsChange(e) {
+ const sendNotificationValue = e.target.value;
+ let pushNotificationServer = this.state.pushNotificationServer;
+ if (sendNotificationValue === 'mtpns') {
+ pushNotificationServer = Constants.MTPNS;
+ } else if (sendNotificationValue === 'mhpns') {
+ pushNotificationServer = Constants.MHPNS;
+ }
+ this.setState({saveNeeded: true, sendNotificationValue, pushNotificationServer, agree: false});
+ }
+
+ handlePushServerChange(e) {
+ this.setState({saveNeeded: true, pushNotificationServer: e.target.value});
+ }
+
+ handleAgreeChange(e) {
+ this.setState({agree: e.target.checked});
+ }
+
handleGenerateInvite(e) {
e.preventDefault();
ReactDOM.findDOMNode(this.refs.InviteSalt).value = crypto.randomBytes(256).toString('base64').substring(0, 32);
@@ -263,6 +311,169 @@ class EmailSettings extends React.Component {
);
}
+ let mhpnsOption;
+ if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MHPNS === 'true') {
+ mhpnsOption = ;
+ }
+
+ let disableSave = !this.state.saveNeeded;
+
+ let tosCheckbox;
+ if (this.state.sendNotificationValue === 'mhpns') {
+ tosCheckbox = (
+
+ );
+
+ disableSave = disableSave || !this.state.agree;
+ }
+
+ let sendHelpText;
+ let pushServerHelpText;
+ if (this.state.sendNotificationValue === 'off') {
+ sendHelpText = (
+
+ );
+ } else if (this.state.sendNotificationValue === 'mhpns') {
+ pushServerHelpText = (
+
+ );
+ } else if (this.state.sendNotificationValue === 'mtpns') {
+ pushServerHelpText = (
+
+ );
+ } else {
+ pushServerHelpText = (
+
+ );
+ }
+
+ const sendPushNotifications = (
+
+
+
+
+
+ {sendHelpText}
+
+
+
+ );
+
+ let pushNotificationServer;
+ let pushNotificationContent;
+ if (this.state.sendNotificationValue !== 'off') {
+ pushNotificationServer = (
+
+
+
+
+
+ {pushServerHelpText}
+
+
+
+ );
+
+ pushNotificationContent = (
+
+
+
+
+
+
+
+
+
+ );
+ }
+
return (
@@ -803,120 +1014,16 @@ class EmailSettings extends React.Component {
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {sendPushNotifications}
+ {tosCheckbox}
+ {pushNotificationServer}
+ {pushNotificationContent}
{serverError}