PLT-902 switching to push proxy server
Этот коммит содержится в:
16
api/post.go
16
api/post.go
@@ -536,7 +536,7 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
|
|||||||
l4g.Error("Failed to send mention email successfully email=%v err=%v", profileMap[id].Email, err)
|
l4g.Error("Failed to send mention email successfully email=%v err=%v", profileMap[id].Email, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(utils.Cfg.EmailSettings.ApplePushServer) > 0 {
|
if *utils.Cfg.EmailSettings.SendPushNotifications {
|
||||||
sessionChan := Srv.Store.Session().GetSessions(id)
|
sessionChan := Srv.Store.Session().GetSessions(id)
|
||||||
if result := <-sessionChan; result.Err != nil {
|
if result := <-sessionChan; result.Err != nil {
|
||||||
l4g.Error("Failed to retrieve sessions in notifications id=%v, err=%v", id, result.Err)
|
l4g.Error("Failed to retrieve sessions in notifications id=%v, err=%v", id, result.Err)
|
||||||
@@ -548,7 +548,19 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
|
|||||||
if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" && strings.HasPrefix(session.DeviceId, "apple:") {
|
if len(session.DeviceId) > 0 && alreadySeen[session.DeviceId] == "" && strings.HasPrefix(session.DeviceId, "apple:") {
|
||||||
alreadySeen[session.DeviceId] = session.DeviceId
|
alreadySeen[session.DeviceId] = session.DeviceId
|
||||||
|
|
||||||
utils.SendAppleNotifyAndForget(strings.TrimPrefix(session.DeviceId, "apple:"), subjectPage.Render(), 1)
|
msg := model.PushNotification{}
|
||||||
|
msg.Platform = model.PUSH_NOTIFY_APPLE
|
||||||
|
msg.Message = subjectPage.Render()
|
||||||
|
msg.Badge = 1
|
||||||
|
msg.DeviceId = strings.TrimPrefix(session.DeviceId, "apple:")
|
||||||
|
msg.ServerId = utils.CfgDiagnosticId
|
||||||
|
|
||||||
|
httpClient := http.Client{}
|
||||||
|
request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+"/api/v1/send_push", strings.NewReader(msg.ToJson()))
|
||||||
|
|
||||||
|
if _, err := httpClient.Do(request); err != nil {
|
||||||
|
l4g.Error("Failed to send push notificationid=%v, err=%v", id, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,9 +68,8 @@
|
|||||||
"ConnectionSecurity": "",
|
"ConnectionSecurity": "",
|
||||||
"InviteSalt": "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9YoS",
|
"InviteSalt": "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9YoS",
|
||||||
"PasswordResetSalt": "vZ4DcKyVVRlKHHJpexcuXzojkE5PZ5eL",
|
"PasswordResetSalt": "vZ4DcKyVVRlKHHJpexcuXzojkE5PZ5eL",
|
||||||
"ApplePushServer": "",
|
"SendPushNotifications": true,
|
||||||
"ApplePushCertPublic": "",
|
"PushNotificationServer": "https://push.mattermost.com"
|
||||||
"ApplePushCertPrivate": ""
|
|
||||||
},
|
},
|
||||||
"RateLimitSettings": {
|
"RateLimitSettings": {
|
||||||
"EnableRateLimiter": true,
|
"EnableRateLimiter": true,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ func main() {
|
|||||||
manualtesting.InitManualTesting()
|
manualtesting.InitManualTesting()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDiagnosticId()
|
||||||
runSecurityAndDiagnosticsJobAndForget()
|
runSecurityAndDiagnosticsJobAndForget()
|
||||||
|
|
||||||
// wait for kill signal before attempting to gracefully shutdown
|
// wait for kill signal before attempting to gracefully shutdown
|
||||||
@@ -80,6 +81,21 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setDiagnosticId() {
|
||||||
|
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
|
||||||
|
props := result.Data.(model.StringMap)
|
||||||
|
|
||||||
|
id := props[model.SYSTEM_DIAGNOSTIC_ID]
|
||||||
|
if len(id) == 0 {
|
||||||
|
id = model.NewId()
|
||||||
|
systemId := &model.System{Name: model.SYSTEM_DIAGNOSTIC_ID, Value: id}
|
||||||
|
<-api.Srv.Store.System().Save(systemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.CfgDiagnosticId = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func runSecurityAndDiagnosticsJobAndForget() {
|
func runSecurityAndDiagnosticsJobAndForget() {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@@ -92,15 +108,9 @@ func runSecurityAndDiagnosticsJobAndForget() {
|
|||||||
if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
|
if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
|
||||||
l4g.Debug("Checking for security update from Mattermost")
|
l4g.Debug("Checking for security update from Mattermost")
|
||||||
|
|
||||||
id := props[model.SYSTEM_DIAGNOSTIC_ID]
|
|
||||||
if len(id) == 0 {
|
|
||||||
id = model.NewId()
|
|
||||||
systemId := &model.System{Name: model.SYSTEM_DIAGNOSTIC_ID, Value: id}
|
|
||||||
<-api.Srv.Store.System().Save(systemId)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set(utils.PROP_DIAGNOSTIC_ID, id)
|
|
||||||
|
v.Set(utils.PROP_DIAGNOSTIC_ID, utils.CfgDiagnosticId)
|
||||||
v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
|
v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
|
||||||
v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
|
v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
|
||||||
v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
|
v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
|
||||||
|
|||||||
@@ -96,11 +96,8 @@ type EmailSettings struct {
|
|||||||
ConnectionSecurity string
|
ConnectionSecurity string
|
||||||
InviteSalt string
|
InviteSalt string
|
||||||
PasswordResetSalt string
|
PasswordResetSalt string
|
||||||
|
SendPushNotifications *bool
|
||||||
// For Future Use
|
PushNotificationServer *string
|
||||||
ApplePushServer string
|
|
||||||
ApplePushCertPublic string
|
|
||||||
ApplePushCertPrivate string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RateLimitSettings struct {
|
type RateLimitSettings struct {
|
||||||
@@ -181,6 +178,17 @@ func (o *Config) SetDefaults() {
|
|||||||
o.TeamSettings.EnableTeamListing = new(bool)
|
o.TeamSettings.EnableTeamListing = new(bool)
|
||||||
*o.TeamSettings.EnableTeamListing = false
|
*o.TeamSettings.EnableTeamListing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.EmailSettings.SendPushNotifications == nil {
|
||||||
|
o.EmailSettings.SendPushNotifications = new(bool)
|
||||||
|
*o.EmailSettings.SendPushNotifications = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.EmailSettings.PushNotificationServer == nil {
|
||||||
|
o.EmailSettings.PushNotificationServer = new(string)
|
||||||
|
*o.EmailSettings.PushNotificationServer = "https://push.mattermost.com"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Config) IsValid() *AppError {
|
func (o *Config) IsValid() *AppError {
|
||||||
|
|||||||
45
model/push_notification.go
Обычный файл
45
model/push_notification.go
Обычный файл
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PUSH_NOTIFY_APPLE = "apple"
|
||||||
|
PUSH_NOTIFY_ANDROID = "android"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushNotification struct {
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
ServerId string `json:"server_id"`
|
||||||
|
DeviceId string `json:"device_id"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
Sound string `json:"sound"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Badge int `json:"badge"`
|
||||||
|
ContentAvailable int `json:"cont_ava"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (me *PushNotification) ToJson() string {
|
||||||
|
b, err := json.Marshal(me)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PushNotificationFromJson(data io.Reader) *PushNotification {
|
||||||
|
decoder := json.NewDecoder(data)
|
||||||
|
var me PushNotification
|
||||||
|
err := decoder.Decode(&me)
|
||||||
|
if err == nil {
|
||||||
|
return &me
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
19
model/push_notification_test.go
Обычный файл
19
model/push_notification_test.go
Обычный файл
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPushNotification(t *testing.T) {
|
||||||
|
msg := PushNotification{Platform: "test"}
|
||||||
|
json := msg.ToJson()
|
||||||
|
result := PushNotificationFromJson(strings.NewReader(json))
|
||||||
|
|
||||||
|
if msg.Platform != result.Platform {
|
||||||
|
t.Fatal("Ids do not match")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
l4g "code.google.com/p/log4go"
|
|
||||||
"fmt"
|
|
||||||
"github.com/anachronistic/apns"
|
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SendAppleNotifyAndForget(deviceId string, message string, badge int) {
|
|
||||||
go func() {
|
|
||||||
if err := SendAppleNotify(deviceId, message, badge); err != nil {
|
|
||||||
l4g.Error(fmt.Sprintf("%v %v", err.Message, err.DetailedError))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendAppleNotify(deviceId string, message string, badge int) *model.AppError {
|
|
||||||
payload := apns.NewPayload()
|
|
||||||
payload.Alert = message
|
|
||||||
payload.Badge = 1
|
|
||||||
|
|
||||||
pn := apns.NewPushNotification()
|
|
||||||
pn.DeviceToken = deviceId
|
|
||||||
pn.AddPayload(payload)
|
|
||||||
client := apns.BareClient(Cfg.EmailSettings.ApplePushServer, Cfg.EmailSettings.ApplePushCertPublic, Cfg.EmailSettings.ApplePushCertPrivate)
|
|
||||||
resp := client.Send(pn)
|
|
||||||
|
|
||||||
if resp.Error != nil {
|
|
||||||
return model.NewAppError("", "Could not send apple push notification", fmt.Sprintf("id=%v err=%v", deviceId, resp.Error))
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var Cfg *model.Config = &model.Config{}
|
var Cfg *model.Config = &model.Config{}
|
||||||
|
var CfgDiagnosticId = ""
|
||||||
var CfgLastModified int64 = 0
|
var CfgLastModified int64 = 0
|
||||||
var CfgFileName string = ""
|
var CfgFileName string = ""
|
||||||
var ClientCfg map[string]string = map[string]string{}
|
var ClientCfg map[string]string = map[string]string{}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export default class EmailSettings extends React.Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
sendEmailNotifications: this.props.config.EmailSettings.SendEmailNotifications,
|
sendEmailNotifications: this.props.config.EmailSettings.SendEmailNotifications,
|
||||||
|
sendPushNotifications: this.props.config.EmailSettings.SendPushNotifications,
|
||||||
saveNeeded: false,
|
saveNeeded: false,
|
||||||
serverError: null,
|
serverError: null,
|
||||||
emailSuccess: null,
|
emailSuccess: null,
|
||||||
@@ -36,6 +37,14 @@ export default class EmailSettings extends React.Component {
|
|||||||
s.sendEmailNotifications = false;
|
s.sendEmailNotifications = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === 'sendPushNotifications_true') {
|
||||||
|
s.sendPushNotifications = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'sendPushNotifications_false') {
|
||||||
|
s.sendPushNotifications = false;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState(s);
|
this.setState(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,11 +52,12 @@ export default class EmailSettings extends React.Component {
|
|||||||
var config = this.props.config;
|
var config = this.props.config;
|
||||||
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
||||||
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||||
|
config.EmailSettings.SendPushlNotifications = ReactDOM.findDOMNode(this.refs.sendPushNotifications).checked;
|
||||||
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
|
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
|
||||||
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
|
||||||
config.EmailSettings.FeedbackName = ReactDOM.findDOMNode(this.refs.feedbackName).value.trim();
|
config.EmailSettings.FeedbackName = ReactDOM.findDOMNode(this.refs.feedbackName).value.trim();
|
||||||
config.EmailSettings.FeedbackEmail = ReactDOM.findDOMNode(this.refs.feedbackEmail).value.trim();
|
config.EmailSettings.FeedbackEmail = ReactDOM.findDOMNode(this.refs.feedbackEmail).value.trim();
|
||||||
config.EmailSettings.SMTPServer = ReactDOM.findDOMNode(this.refs.SMTPServer).value.trim();
|
config.EmailSettings.SMTPServer = ReactDOM.findDOMNode(this.refs.SMTPServer).value.trim();
|
||||||
|
config.EmailSettings.PushNotificationServer = ReactDOM.findDOMNode(this.refs.PushNotificationServer).value.trim();
|
||||||
config.EmailSettings.SMTPPort = ReactDOM.findDOMNode(this.refs.SMTPPort).value.trim();
|
config.EmailSettings.SMTPPort = ReactDOM.findDOMNode(this.refs.SMTPPort).value.trim();
|
||||||
config.EmailSettings.SMTPUsername = ReactDOM.findDOMNode(this.refs.SMTPUsername).value.trim();
|
config.EmailSettings.SMTPUsername = ReactDOM.findDOMNode(this.refs.SMTPUsername).value.trim();
|
||||||
config.EmailSettings.SMTPPassword = ReactDOM.findDOMNode(this.refs.SMTPPassword).value.trim();
|
config.EmailSettings.SMTPPassword = ReactDOM.findDOMNode(this.refs.SMTPPassword).value.trim();
|
||||||
@@ -525,6 +535,61 @@ export default class EmailSettings extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='form-group'>
|
||||||
|
<label
|
||||||
|
className='control-label col-sm-4'
|
||||||
|
htmlFor='sendPushNotifications'
|
||||||
|
>
|
||||||
|
{'Send Push Notifications: '}
|
||||||
|
</label>
|
||||||
|
<div className='col-sm-8'>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='sendPushNotifications'
|
||||||
|
value='true'
|
||||||
|
ref='sendPushNotifications'
|
||||||
|
defaultChecked={this.props.config.EmailSettings.SendPushNotifications}
|
||||||
|
onChange={this.handleChange.bind(this, 'sendPushNotifications_true')}
|
||||||
|
/>
|
||||||
|
{'true'}
|
||||||
|
</label>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='sendPushNotifications'
|
||||||
|
value='false'
|
||||||
|
defaultChecked={!this.props.config.EmailSettings.SendPushNotifications}
|
||||||
|
onChange={this.handleChange.bind(this, 'sendPushNotifications_false')}
|
||||||
|
/>
|
||||||
|
{'false'}
|
||||||
|
</label>
|
||||||
|
<p className='help-text'>{'Typically set to true in production. When true, Mattermost attempts to send iOS and Android push notifications through the push notification server.'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='form-group'>
|
||||||
|
<label
|
||||||
|
className='control-label col-sm-4'
|
||||||
|
htmlFor='PushNotificationServer'
|
||||||
|
>
|
||||||
|
{'Push Notification Server:'}
|
||||||
|
</label>
|
||||||
|
<div className='col-sm-8'>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
className='form-control'
|
||||||
|
id='PushNotificationServer'
|
||||||
|
ref='PushNotificationServer'
|
||||||
|
placeholder='E.g.: "https://push.mattermost.com"'
|
||||||
|
defaultValue={this.props.config.EmailSettings.PushNotificationServer}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
disabled={!this.state.sendPushNotifications}
|
||||||
|
/>
|
||||||
|
<p className='help-text'>{'Location of the push notification server.'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<div className='col-sm-12'>
|
<div className='col-sm-12'>
|
||||||
{serverError}
|
{serverError}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user