feat(iOS): load iOS key from base64 input. (#336)

* feat(iOS): load iOS key from base64 input.

* test: check key type exist.
This commit is contained in:
Bo-Yi Wu 2018-02-18 17:12:51 +08:00 committed by GitHub
parent c3167f77f3
commit 2d2f62d19b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 129 additions and 20 deletions

View File

@ -83,6 +83,8 @@ core:
ssl: false ssl: false
cert_path: "cert.pem" cert_path: "cert.pem"
key_path: "key.pem" key_path: "key.pem"
cert_base64: ""
key_base64: ""
http_proxy: "" # only working for FCM server http_proxy: "" # only working for FCM server
pid: pid:
enabled: false enabled: false
@ -114,6 +116,8 @@ android:
ios: ios:
enabled: false enabled: false
key_path: "key.pem" key_path: "key.pem"
key_base64: "" # load iOS key from base64 input
key_type: "pem" # could be pem, p12 or p8 type
password: "" # certificate password, default as empty string. password: "" # certificate password, default as empty string.
production: false production: false
max_retry: 0 # resend fail notification, default value zero is disabled max_retry: 0 # resend fail notification, default value zero is disabled

View File

@ -23,6 +23,8 @@ core:
ssl: false ssl: false
cert_path: "cert.pem" cert_path: "cert.pem"
key_path: "key.pem" key_path: "key.pem"
cert_base64: ""
key_base64: ""
http_proxy: "" # only working for FCM server http_proxy: "" # only working for FCM server
pid: pid:
enabled: false enabled: false
@ -54,6 +56,8 @@ android:
ios: ios:
enabled: false enabled: false
key_path: "key.pem" key_path: "key.pem"
key_base64: "" # load iOS key from base64 input
key_type: "pem" # could be pem, p12 or p8 type
password: "" # certificate password, default as empty string. password: "" # certificate password, default as empty string.
production: false production: false
max_retry: 0 # resend fail notification, default value zero is disabled max_retry: 0 # resend fail notification, default value zero is disabled
@ -107,6 +111,8 @@ type SectionCore struct {
SSL bool `yaml:"ssl"` SSL bool `yaml:"ssl"`
CertPath string `yaml:"cert_path"` CertPath string `yaml:"cert_path"`
KeyPath string `yaml:"key_path"` KeyPath string `yaml:"key_path"`
CertBase64 string `yaml:"cert_base64"`
KeyBase64 string `yaml:"key_base64"`
HTTPProxy string `yaml:"http_proxy"` HTTPProxy string `yaml:"http_proxy"`
PID SectionPID `yaml:"pid"` PID SectionPID `yaml:"pid"`
AutoTLS SectionAutoTLS `yaml:"auto_tls"` AutoTLS SectionAutoTLS `yaml:"auto_tls"`
@ -141,6 +147,8 @@ type SectionAndroid struct {
type SectionIos struct { type SectionIos struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`
KeyPath string `yaml:"key_path"` KeyPath string `yaml:"key_path"`
KeyBase64 string `yaml:"key_base64"`
KeyType string `yaml:"key_type"`
Password string `yaml:"password"` Password string `yaml:"password"`
Production bool `yaml:"production"` Production bool `yaml:"production"`
MaxRetry int `yaml:"max_retry"` MaxRetry int `yaml:"max_retry"`
@ -247,6 +255,8 @@ func LoadConf(confPath string) (ConfYaml, error) {
conf.Core.SSL = viper.GetBool("core.ssl") conf.Core.SSL = viper.GetBool("core.ssl")
conf.Core.CertPath = viper.GetString("core.cert_path") conf.Core.CertPath = viper.GetString("core.cert_path")
conf.Core.KeyPath = viper.GetString("core.key_path") conf.Core.KeyPath = viper.GetString("core.key_path")
conf.Core.CertBase64 = viper.GetString("core.cert_base64")
conf.Core.KeyBase64 = viper.GetString("core.key_base64")
conf.Core.MaxNotification = int64(viper.GetInt("core.max_notification")) conf.Core.MaxNotification = int64(viper.GetInt("core.max_notification"))
conf.Core.HTTPProxy = viper.GetString("core.http_proxy") conf.Core.HTTPProxy = viper.GetString("core.http_proxy")
conf.Core.PID.Enabled = viper.GetBool("core.pid.enabled") conf.Core.PID.Enabled = viper.GetBool("core.pid.enabled")
@ -273,6 +283,8 @@ func LoadConf(confPath string) (ConfYaml, error) {
// iOS // iOS
conf.Ios.Enabled = viper.GetBool("ios.enabled") conf.Ios.Enabled = viper.GetBool("ios.enabled")
conf.Ios.KeyPath = viper.GetString("ios.key_path") conf.Ios.KeyPath = viper.GetString("ios.key_path")
conf.Ios.KeyBase64 = viper.GetString("ios.key_base64")
conf.Ios.KeyType = viper.GetString("ios.key_type")
conf.Ios.Password = viper.GetString("ios.password") conf.Ios.Password = viper.GetString("ios.password")
conf.Ios.Production = viper.GetBool("ios.production") conf.Ios.Production = viper.GetBool("ios.production")
conf.Ios.MaxRetry = viper.GetInt("ios.max_retry") conf.Ios.MaxRetry = viper.GetInt("ios.max_retry")

View File

@ -10,6 +10,8 @@ core:
ssl: false ssl: false
cert_path: "cert.pem" cert_path: "cert.pem"
key_path: "key.pem" key_path: "key.pem"
cert_base64: ""
key_base64: ""
http_proxy: "" # only working for FCM server http_proxy: "" # only working for FCM server
pid: pid:
enabled: false enabled: false
@ -41,6 +43,8 @@ android:
ios: ios:
enabled: false enabled: false
key_path: "key.pem" key_path: "key.pem"
key_base64: "" # load iOS key from base64 input
key_type: "pem" # could be pem, p12 or p8 type
password: "" # certificate password, default as empty string. password: "" # certificate password, default as empty string.
production: false production: false
max_retry: 0 # resend fail notification, default value zero is disabled max_retry: 0 # resend fail notification, default value zero is disabled

View File

@ -47,6 +47,8 @@ func (suite *ConfigTestSuite) TestValidateConfDefault() {
assert.Equal(suite.T(), false, suite.ConfGorushDefault.Core.SSL) assert.Equal(suite.T(), false, suite.ConfGorushDefault.Core.SSL)
assert.Equal(suite.T(), "cert.pem", suite.ConfGorushDefault.Core.CertPath) assert.Equal(suite.T(), "cert.pem", suite.ConfGorushDefault.Core.CertPath)
assert.Equal(suite.T(), "key.pem", suite.ConfGorushDefault.Core.KeyPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorushDefault.Core.KeyPath)
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Core.KeyBase64)
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Core.CertBase64)
assert.Equal(suite.T(), int64(100), suite.ConfGorushDefault.Core.MaxNotification) assert.Equal(suite.T(), int64(100), suite.ConfGorushDefault.Core.MaxNotification)
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Core.HTTPProxy) assert.Equal(suite.T(), "", suite.ConfGorushDefault.Core.HTTPProxy)
// Pid // Pid
@ -74,6 +76,8 @@ func (suite *ConfigTestSuite) TestValidateConfDefault() {
// iOS // iOS
assert.Equal(suite.T(), false, suite.ConfGorushDefault.Ios.Enabled) assert.Equal(suite.T(), false, suite.ConfGorushDefault.Ios.Enabled)
assert.Equal(suite.T(), "key.pem", suite.ConfGorushDefault.Ios.KeyPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorushDefault.Ios.KeyPath)
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.KeyBase64)
assert.Equal(suite.T(), "pem", suite.ConfGorushDefault.Ios.KeyType)
assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.Password) assert.Equal(suite.T(), "", suite.ConfGorushDefault.Ios.Password)
assert.Equal(suite.T(), false, suite.ConfGorushDefault.Ios.Production) assert.Equal(suite.T(), false, suite.ConfGorushDefault.Ios.Production)
assert.Equal(suite.T(), 0, suite.ConfGorushDefault.Ios.MaxRetry) assert.Equal(suite.T(), 0, suite.ConfGorushDefault.Ios.MaxRetry)
@ -115,6 +119,8 @@ func (suite *ConfigTestSuite) TestValidateConf() {
assert.Equal(suite.T(), false, suite.ConfGorush.Core.SSL) assert.Equal(suite.T(), false, suite.ConfGorush.Core.SSL)
assert.Equal(suite.T(), "cert.pem", suite.ConfGorush.Core.CertPath) assert.Equal(suite.T(), "cert.pem", suite.ConfGorush.Core.CertPath)
assert.Equal(suite.T(), "key.pem", suite.ConfGorush.Core.KeyPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorush.Core.KeyPath)
assert.Equal(suite.T(), "", suite.ConfGorush.Core.CertBase64)
assert.Equal(suite.T(), "", suite.ConfGorush.Core.KeyBase64)
assert.Equal(suite.T(), int64(100), suite.ConfGorush.Core.MaxNotification) assert.Equal(suite.T(), int64(100), suite.ConfGorush.Core.MaxNotification)
assert.Equal(suite.T(), "", suite.ConfGorush.Core.HTTPProxy) assert.Equal(suite.T(), "", suite.ConfGorush.Core.HTTPProxy)
// Pid // Pid
@ -142,6 +148,8 @@ func (suite *ConfigTestSuite) TestValidateConf() {
// iOS // iOS
assert.Equal(suite.T(), false, suite.ConfGorush.Ios.Enabled) assert.Equal(suite.T(), false, suite.ConfGorush.Ios.Enabled)
assert.Equal(suite.T(), "key.pem", suite.ConfGorush.Ios.KeyPath) assert.Equal(suite.T(), "key.pem", suite.ConfGorush.Ios.KeyPath)
assert.Equal(suite.T(), "", suite.ConfGorush.Ios.KeyBase64)
assert.Equal(suite.T(), "pem", suite.ConfGorush.Ios.KeyType)
assert.Equal(suite.T(), "", suite.ConfGorush.Ios.Password) assert.Equal(suite.T(), "", suite.ConfGorush.Ios.Password)
assert.Equal(suite.T(), false, suite.ConfGorush.Ios.Production) assert.Equal(suite.T(), false, suite.ConfGorush.Ios.Production)
assert.Equal(suite.T(), 0, suite.ConfGorush.Ios.MaxRetry) assert.Equal(suite.T(), 0, suite.ConfGorush.Ios.MaxRetry)

View File

@ -172,15 +172,17 @@ func CheckPushConf() error {
} }
if PushConf.Ios.Enabled { if PushConf.Ios.Enabled {
if PushConf.Ios.KeyPath == "" { if PushConf.Ios.KeyPath == "" && PushConf.Ios.KeyBase64 == "" {
return errors.New("Missing iOS certificate path") return errors.New("Missing iOS certificate key")
} }
// check certificate file exist // check certificate file exist
if PushConf.Ios.KeyPath != "" {
if _, err := os.Stat(PushConf.Ios.KeyPath); os.IsNotExist(err) { if _, err := os.Stat(PushConf.Ios.KeyPath); os.IsNotExist(err) {
return errors.New("certificate file does not exist") return errors.New("certificate file does not exist")
} }
} }
}
if PushConf.Android.Enabled { if PushConf.Android.Enabled {
if PushConf.Android.APIKey == "" { if PushConf.Android.APIKey == "" {

View File

@ -3,6 +3,7 @@ package gorush
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/tls" "crypto/tls"
"encoding/base64"
"errors" "errors"
"path/filepath" "path/filepath"
"time" "time"
@ -19,7 +20,10 @@ func InitAPNSClient() error {
var err error var err error
var authKey *ecdsa.PrivateKey var authKey *ecdsa.PrivateKey
var certificateKey tls.Certificate var certificateKey tls.Certificate
ext := filepath.Ext(PushConf.Ios.KeyPath) var ext string
if PushConf.Ios.KeyPath != "" {
ext = filepath.Ext(PushConf.Ios.KeyPath)
switch ext { switch ext {
case ".p12": case ".p12":
@ -37,6 +41,31 @@ func InitAPNSClient() error {
return err return err
} }
} else if PushConf.Ios.KeyBase64 != "" {
ext = "." + PushConf.Ios.KeyType
key, err := base64.StdEncoding.DecodeString(PushConf.Ios.KeyBase64)
if err != nil {
LogError.Error("base64 decode error:", err.Error())
return err
}
switch ext {
case ".p12":
certificateKey, err = certificate.FromP12Bytes(key, PushConf.Ios.Password)
case ".pem":
certificateKey, err = certificate.FromPemBytes(key, PushConf.Ios.Password)
case ".p8":
authKey, err = token.AuthKeyFromBytes(key)
default:
err = errors.New("wrong certificate key type")
}
if err != nil {
LogError.Error("Cert Error:", err.Error())
return err
}
}
if ext == ".p8" && PushConf.Ios.KeyID != "" && PushConf.Ios.TeamID != "" { if ext == ".p8" && PushConf.Ios.KeyID != "" && PushConf.Ios.TeamID != "" {
token := &token.Token{ token := &token.Token{

View File

@ -13,6 +13,14 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
const certificateValidP12 = `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`
const certificateValidPEM = `QmFnIEF0dHJpYnV0ZXMKICAgIGxvY2FsS2V5SUQ6IDhDIDFBIDlGIDAwIDY2IEJEIDI0IDQyIEI5IDVEIDFFIEVCIEZFIDVFIDhCIENBIDA0IDNEIDczIDgzIAogICAgZnJpZW5kbHlOYW1lOiBBUE5TLzIgUHJpdmF0ZSBLZXkKc3ViamVjdD0vQz1OWi9TVD1XZWxsaW5ndG9uL0w9V2VsbGluZ3Rvbi9PPUludGVybmV0IFdpZGdpdHMgUHR5IEx0ZC9PVT05WkVINjJLUlZWL0NOPUFQTlMvMiBEZXZlbG9wbWVudCBJT1MgUHVzaCBTZXJ2aWNlczogY29tLnNpZGVzaG93LkFwbnMyCmlzc3Vlcj0vQz1OWi9TVD1XZWxsaW5ndG9uL0w9V2VsbGluZ3Rvbi9PPUFQTlMvMiBJbmMuL09VPUFQTlMvMiBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9ucy9DTj1BUE5TLzIgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQ2ekNDQXRNQ0FRSXdEUVlKS29aSWh2Y05BUUVMQlFBd2djTXhDekFKQmdOVkJBWVRBazVhTVJNd0VRWUQKVlFRSUV3cFhaV3hzYVc1bmRHOXVNUk13RVFZRFZRUUhFd3BYWld4c2FXNW5kRzl1TVJRd0VnWURWUVFLRXd0QgpVRTVUTHpJZ1NXNWpMakV0TUNzR0ExVUVDeE1rUVZCT1V5OHlJRmR2Y214a2QybGtaU0JFWlhabGJHOXdaWElnClVtVnNZWFJwYjI1ek1VVXdRd1lEVlFRREV6eEJVRTVUTHpJZ1YyOXliR1IzYVdSbElFUmxkbVZzYjNCbGNpQlMKWld4aGRHbHZibk1nUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3dIaGNOTVRZd01UQTRNRGd6TkRNdwpXaGNOTWpZd01UQTFNRGd6TkRNd1dqQ0JzakVMTUFrR0ExVUVCaE1DVGxveEV6QVJCZ05WQkFnVENsZGxiR3hwCmJtZDBiMjR4RXpBUkJnTlZCQWNUQ2xkbGJHeHBibWQwYjI0eElUQWZCZ05WQkFvVEdFbHVkR1Z5Ym1WMElGZHAKWkdkcGRITWdVSFI1SUV4MFpERVRNQkVHQTFVRUN4TUtPVnBGU0RZeVMxSldWakZCTUQ4R0ExVUVBeE00UVZCTwpVeTh5SUVSbGRtVnNiM0J0Wlc1MElFbFBVeUJRZFhOb0lGTmxjblpwWTJWek9pQmpiMjB1YzJsa1pYTm9iM2N1ClFYQnVjekl3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRFkwYzFUS0I1b1pQd1EKN3QxQ3dNSXJ2cUI2R0lVM3RQeTZSaGNrWlhUa09COFllQldKN1VLZkN6OEhHSEZWb21CUDBUNU9VYmVxUXpxVwpZSmJRelo4YTZaTXN6YkwwbE80WDkrKzNPaTUvVHRBd09VT0s4ck9GTjI1bTJLZnNheUhRWi80dldTdEsyRndtCjVhSmJHTGxwSC9iLzd6MUQ0dmhtTWdvQnVUMUl1eWhHaXlGeGxaOUV0VGxvRnZzcU0xRTVmWVpPU1pBQ3lYVGEKSzR2ZGdiUU1nVVZzSTcxNEZBZ0xUbEswVWVpUmttS20zcGRidGZWYnJ0aHpJK0lIWEtJdFVJeStGbjIwUFJNaApkU25henRTejd0Z0JXQ0l4MjJxdmNZb2dIV2lPZ1VZSU03NzJ6RTJ5OFVWT3I4RHNpUmxzT0hTQTdFSTRNSmNRCkcyRlVxMlovQWdNQkFBRXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBR3lmeU8ySE1nY2RlQmN6M2J0NUJJTFgKZjdSQTIvVW1WSXdjS1IxcW90VHNGK1BuQm1jSUxleU9RZ0RlOXRHVTVjUmM3OWtEdDNKUm1NWVJPRklNZ0ZSZgpXZjIydU9LdGhvN0dRUWFLdkcrYmtnTVZkWUZSbEJIbkYrS2VxS0g4MXFiOXArQ1Q0SXcwR2VoSUwxRGlqRkxSClZJQUlCWXB6NG9CUENJRTFJU1ZUK0ZnYWYzSkFoNTlrYlBiTnc5QUlEeGFCdFA4RXV6U1ROd2ZieG9HYkNvYlMKV2kxVThJc0N3UUZ0OHRNMW00WlhEMUNjWklyR2RyeWVBaFZrdktJSlJpVTVRWVdJMm5xWk4rSnFRdWNtOWFkMAptWU81bUprSW9iVWE0K1pKaENQS0VkbWdwRmJSR2swd1Z1YURNOUN2NlAyc3JzWUFqYU80eTNWUDBHdk5LUkk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KQmFnIEF0dHJpYnV0ZXMKICAgIGxvY2FsS2V5SUQ6IDhDIDFBIDlGIDAwIDY2IEJEIDI0IDQyIEI5IDVEIDFFIEVCIEZFIDVFIDhCIENBIDA0IDNEIDczIDgzIAogICAgZnJpZW5kbHlOYW1lOiBBUE5TLzIgUHJpdmF0ZSBLZXkKS2V5IEF0dHJpYnV0ZXM6IDxObyBBdHRyaWJ1dGVzPgotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tCk1JSUVvd0lCQUFLQ0FRRUEyTkhOVXlnZWFHVDhFTzdkUXNEQ0s3NmdlaGlGTjdUOHVrWVhKR1YwNURnZkdIZ1YKaWUxQ253cy9CeGh4VmFKZ1Q5RStUbEczcWtNNmxtQ1cwTTJmR3VtVExNMnk5SlR1Ri9mdnR6b3VmMDdRTURsRAppdkt6aFRkdVp0aW43R3NoMEdmK0wxa3JTdGhjSnVXaVd4aTVhUi8yLys4OVErTDRaaklLQWJrOVNMc29Sb3NoCmNaV2ZSTFU1YUJiN0tqTlJPWDJHVGttUUFzbDAyaXVMM1lHMERJRkZiQ085ZUJRSUMwNVN0Rkhva1pKaXB0NlgKVzdYMVc2N1ljeVBpQjF5aUxWQ012aFo5dEQwVElYVXAyczdVcys3WUFWZ2lNZHRxcjNHS0lCMW9qb0ZHQ0RPKwo5c3hOc3ZGRlRxL0E3SWtaYkRoMGdPeENPRENYRUJ0aFZLdG1md0lEQVFBQkFvSUJBUUNXOFpDSStPQWFlMXRFCmlwWjlGMmJXUDNMSExYVG84RllWZENBK1ZXZUlUazNQb2lJVWtKbVYwYVdDVWhEc3RndG81ZG9EZWo1c0NUdXIKWHZqL3luYWVyTWVxSkZZV2tld2p3WmNnTHlBWnZ3dU8xdjdmcDlFMHgvOVRHRGZuampuUE5lYXVuZHhXMGNOdAp6T1kzbDBIVkhzeTlKcGUzUURjQUpvdnk0VHY1K2hGWTRrRHhVQkdzeWp2aFNjVmdLZzV0TGtKY2xtM3NPdS9MCkd5THFwd05JM09KQWRNSXVWRDROMkJaMWFPRWFwNm1wMnk4SWUwL1I0WVdjYVo1QTRQdzd4VVBsNlNYYzl1dWEKLzc4UVRFUnRQQzZlanlDQmlFMDVhOG0zUTNpdWQzWHRubHl3czJLd2hnQkFmRTZNNHpSL2YzT1FCN1pJWE1oeQpacG1aWnc1eEFvR0JBUFluODRJcmxJUWV0V1FmdlBkTTdLemdoNlVESEN1Z25sQ0RnaHdZcFJKR2k4aE1mdVpWCnhOSXJZQUp6TFlEUTAxbEZKUkpnV1hUY2JxejlOQnoxbmhnK2NOT3oxL0tZKzM4ZXVkZWU2RE5ZbXp0UDdqRFAKMmpuYVMrZHRqQzhoQVhPYm5GcUcrTmlsTURMTHU2YVJtckphSW1ialNyZnlMaUU2bXZKN3U4MW5Bb0dCQU9GOQpnOTN3WjBtTDFyazJzNVd3SEdUTlUvSGFPdG1XUzR6N2tBN2Y0UWFSdWIrTXdwcFptbURaUEhwaVpYN0JQY1p6CmlPUFFoK3huN0lxUkdvUVdCTHlrQlZ0OHpaRm9MWkpvQ1IzbjYzbGV4NUE0cC8wUHAxZ0ZaclIreFg4UFlWb3MKM3llZWlXeVBLc1hYTmMwczVRd0haY1g2V2I4RUhUaFRYR0NCZXRjcEFvR0FNZVFKQzlJUGFQUGNhZTJ3M0NMQQpPWTNNa0ZwZ0JFdXFxc0RzeHdzTHNmZVFiMGxwMHYrQlErTzhzdUpyVDVlRHJxMUFCVWgzK1NLUVlBbDEzWVMrCnhVVXFrdzM1YjljbjZpenRGOUhDV0YzV0lLQmpzNHI5UFFxTXBkeGpORTRwUUNoQytXb3YxNkVyY3JBdVdXVmIKaUZpU2JtNFUvOUZiSGlzRnFxMy9jM01DZ1lCK3Z6U3VQZ0Z3MzcrMG9FRFZ0UVpneXVHU29wNU56Q052ZmIvOQovRzNhYVhORmJuTzhtdjBoenpvbGVNV2dPRExuSis0Y1VBejNIM3RnY0N1OWJ6citaaHYwenZRbDlhOFlDbzZGClZ1V1BkVzByYmcxUE84dE91TXFBVG5ubzc5WkMvOUgzelM5bDdCdVkxVjJTbE5leXFUM1Z5T0ZGYzZTUkVwcHMKVEp1bDhRS0JnQXhuUUI4TUE3elBVTHUxY2x5YUpMZHRFZFJQa0tXTjdsS1lwdGMwZS9WSGZTc0t4c2VXa2ZxaQp6Z1haNTFrUVRyVDZaYjZIWVJmd0MxbU1YSFdSS1J5WWpBbkN4VmltNllRZCtLVlQ0OWlSRERBaUlGb01HQTRpCnZ2Y0lsbmVxT1paUERJb0tKNjBJak8vRFpIV2t3NW1MamFJclQrcVEzWEFHZEpBMTNoY20KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K`
const authkeyInvalidP8 = `TUlHSEFnRUFNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQkcwd2F3SUJBUVFnRWJWemZQblpQeGZBeXhxRQpaVjA1bGFBb0pBbCsvNlh0Mk80bU9CNjExc09oUkFOQ0FBU2dGVEtqd0pBQVU5NWcrKy92ektXSGt6QVZtTk1JCnRCNXZUalpPT0l3bkViNzBNc1daRkl5VUZEMVA5R3dzdHo0K2FrSFg3dkk4Qkg2aEhtQm1mWlpaCg==`
const authkeyValidP8 = `LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ0ViVnpmUG5aUHhmQXl4cUUKWlYwNWxhQW9KQWwrLzZYdDJPNG1PQjYxMXNPaFJBTkNBQVNnRlRLandKQUFVOTVnKysvdnpLV0hrekFWbU5NSQp0QjV2VGpaT09Jd25FYjcwTXNXWkZJeVVGRDFQOUd3c3R6NCtha0hYN3ZJOEJINmhIbUJtZmVRbAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==`
func TestDisabledAndroidIosConf(t *testing.T) { func TestDisabledAndroidIosConf(t *testing.T) {
PushConf, _ = config.LoadConf("") PushConf, _ = config.LoadConf("")
PushConf.Android.Enabled = false PushConf.Android.Enabled = false
@ -28,17 +36,17 @@ func TestMissingIOSCertificate(t *testing.T) {
PushConf.Ios.Enabled = true PushConf.Ios.Enabled = true
PushConf.Ios.KeyPath = "" PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = ""
err := CheckPushConf() err := CheckPushConf()
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "Missing iOS certificate path", err.Error()) assert.Equal(t, "Missing iOS certificate key", err.Error())
PushConf.Ios.KeyPath = "test.pem" PushConf.Ios.KeyPath = "test.pem"
err = CheckPushConf() err = CheckPushConf()
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "certificate file does not exist", err.Error()) assert.Equal(t, "certificate file does not exist", err.Error())
} }
func TestIOSNotificationStructure(t *testing.T) { func TestIOSNotificationStructure(t *testing.T) {
var dat map[string]interface{} var dat map[string]interface{}
@ -396,6 +404,14 @@ func TestWrongIosCertificateExt(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "wrong certificate key extension", err.Error()) assert.Equal(t, "wrong certificate key extension", err.Error())
PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = "abcd"
PushConf.Ios.KeyType = "abcd"
err = InitAPNSClient()
assert.Error(t, err)
assert.Equal(t, "wrong certificate key type", err.Error())
} }
func TestAPNSClientDevHost(t *testing.T) { func TestAPNSClientDevHost(t *testing.T) {
@ -406,6 +422,13 @@ func TestAPNSClientDevHost(t *testing.T) {
err := InitAPNSClient() err := InitAPNSClient()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host) assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = certificateValidP12
PushConf.Ios.KeyType = "p12"
err = InitAPNSClient()
assert.Nil(t, err)
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
} }
func TestAPNSClientProdHost(t *testing.T) { func TestAPNSClientProdHost(t *testing.T) {
@ -417,6 +440,13 @@ func TestAPNSClientProdHost(t *testing.T) {
err := InitAPNSClient() err := InitAPNSClient()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, apns2.HostProduction, ApnsClient.Host) assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = certificateValidPEM
PushConf.Ios.KeyType = "pem"
err = InitAPNSClient()
assert.Nil(t, err)
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
} }
func TestAPNSClientInvaildToken(t *testing.T) { func TestAPNSClientInvaildToken(t *testing.T) {
@ -426,6 +456,12 @@ func TestAPNSClientInvaildToken(t *testing.T) {
PushConf.Ios.KeyPath = "../certificate/authkey-invalid.p8" PushConf.Ios.KeyPath = "../certificate/authkey-invalid.p8"
err := InitAPNSClient() err := InitAPNSClient()
assert.Error(t, err) assert.Error(t, err)
PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = authkeyInvalidP8
PushConf.Ios.KeyType = "p8"
err = InitAPNSClient()
assert.Error(t, err)
} }
func TestAPNSClientVaildToken(t *testing.T) { func TestAPNSClientVaildToken(t *testing.T) {
@ -441,6 +477,20 @@ func TestAPNSClientVaildToken(t *testing.T) {
err = InitAPNSClient() err = InitAPNSClient()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, apns2.HostProduction, ApnsClient.Host) assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
// test base64
PushConf.Ios.Production = false
PushConf.Ios.KeyPath = ""
PushConf.Ios.KeyBase64 = authkeyValidP8
PushConf.Ios.KeyType = "p8"
err = InitAPNSClient()
assert.NoError(t, err)
assert.Equal(t, apns2.HostDevelopment, ApnsClient.Host)
PushConf.Ios.Production = true
err = InitAPNSClient()
assert.NoError(t, err)
assert.Equal(t, apns2.HostProduction, ApnsClient.Host)
} }
func TestPushToIOS(t *testing.T) { func TestPushToIOS(t *testing.T) {