Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding pr template file #9

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bea301d
add token checking expiration checking
cikupin Nov 2, 2019
0f40201
add RenewToken()
cikupin Nov 2, 2019
fa7d02d
update readme
cikupin Nov 5, 2019
eefd209
Merge branch 'feature/renew-jwt-if-expired' into redis-storage
cikupin Nov 6, 2019
7460f98
add redis storage
cikupin Nov 8, 2019
803fa1e
improve redis storage & add getJWTExpiration()
cikupin Nov 8, 2019
860bebd
add token expiration checking
cikupin Nov 11, 2019
cffba98
update go module
cikupin Nov 11, 2019
903d637
Merge pull request #1 from cikupin/redis-storage
cikupin Nov 14, 2019
29cef05
remove verify secret
cikupin Nov 29, 2019
f29f63e
Merge pull request #2 from cikupin/remove-verify-secret
cikupin Nov 29, 2019
25afcaa
fix jwt expired
cikupin Nov 30, 2019
6d77535
Merge pull request #3 from cikupin/fix-jwt-expired
cikupin Nov 30, 2019
c22546c
add send HSM method
cikupin Dec 16, 2019
eac239f
add pre create user & link user to channel method
cikupin Dec 16, 2019
80aeaaf
add basic auth support
cikupin Dec 17, 2019
7021226
add basic auth support
cikupin Dec 17, 2019
5368fd4
add response data for http status & response flag
cikupin Dec 17, 2019
1854333
update unit test
cikupin Dec 17, 2019
2fa10fc
Merge pull request #4 from cikupin/feature/add-user
cikupin Dec 17, 2019
9344dc9
export struct
cikupin Dec 17, 2019
5f77f64
Merge pull request #5 from cikupin/feature/add-user
cikupin Dec 17, 2019
4ad827f
add mapstructure
cikupin Dec 17, 2019
f3e235b
Merge pull request #6 from cikupin/feature/add-user
cikupin Dec 17, 2019
8b7ce6c
allow blank surname
cikupin Jan 6, 2020
29daa7a
Merge pull request #7 from cikupin/allow-blank-surname
cikupin Jan 6, 2020
927a61b
Updating Pull Request Template 2020-02-17
ardityawahyu Feb 17, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,69 @@

This is a Go library for making bots with Smooch service.

_**Note** : This a modified version version of [EddyTravels/smooch](https://github.com/EddyTravels/smooch) library with additional features. Please refer to the original repo for the original features._

## Additional Feature

- Token expiration & its checking.
- Pre-create app user and link app user to specified channel functionality.
- Send message in whatsapp HSM format.
- Renew token functionality whenever token is expired.
- Support smooch basic auth and JWT auth.
- Redis support as a centralized storage to store JWT token for supporting autoscaling environment. Use redigo as redis library.

## Tips

Smooch documentation: https://docs.smooch.io/rest/

## Installing

```
$ go get -u github.com/EddyTravels/smooch
$ go get -u github.com/kitabisa/smooch
```

## Example

Using basic authentication :


```
import (
"os"

"github.com/kitabisa/smooch"
)

func main() {
smoochClient, err := smooch.New(smooch.Options{
Auth: smooch.AuthBasic,
AppID: os.Getenv("SMOOCH_APP_ID"),
KeyID: os.Getenv("SMOOCH_KEY_ID"),
Secret: os.Getenv("SMOOCH_SECRET"),
})

if err != nil {
panic(err)
}
}
```

Using JWT authentication :

```
import (
"os"

"github.com/EddyTravels/smooch"
"github.com/kitabisa/smooch"
)

func main() {
smoochClient, err := smooch.New(smooch.Options{
Auth: smooch.AuthJWT,
AppID: os.Getenv("SMOOCH_APP_ID"),
KeyID: os.Getenv("SMOOCH_KEY_ID"),
Secret: os.Getenv("SMOOCH_SECRET"),
VerifySecret: os.Getenv("SMOOCH_VERIFY_SECRET"),
RedisPool: redisPool,
})

if err != nil {
Expand Down
16 changes: 13 additions & 3 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import (
"net/http"
)

// ResponseData defines data for every response
type ResponseData struct {
HTTPCode int
Flag string
}

type SmoochError struct {
message string
code int
Expand All @@ -19,11 +25,11 @@ func (e *SmoochError) Error() string {
return e.message
}

func checkSmoochError(r *http.Response) error {
func checkSmoochError(r *http.Response) (*ResponseData, error) {
var errorPayload ErrorPayload
decodeErr := json.NewDecoder(r.Body).Decode(&errorPayload)
if decodeErr != nil {
return decodeErr
return nil, decodeErr
}

err := &SmoochError{
Expand All @@ -35,5 +41,9 @@ func checkSmoochError(r *http.Response) error {
code: r.StatusCode,
}

return err
respData := &ResponseData{
HTTPCode: r.StatusCode,
Flag: errorPayload.Details.Code,
}
return respData, err
}
2 changes: 1 addition & 1 deletion error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestCheckSmoochError(t *testing.T) {
Body: r,
}

err := checkSmoochError(response)
_, err := checkSmoochError(response)
assert.Error(t, err)
assert.EqualError(t, err, "StatusCode: 401 Code: unauthorized Message: Authorization is required")
}
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
module github.com/EddyTravels/smooch
module github.com/kitabisa/smooch

require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gomodule/redigo v2.0.0+incompatible
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/stretchr/testify v1.3.0
)

go 1.13
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/kitabisa/smooch v0.1.0 h1:dS+ouObVdoNFVZWMIqULMr/VbQoYhsBuSUdmp0VjbcM=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
41 changes: 41 additions & 0 deletions jwt.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package smooch

import (
"time"

jwt "github.com/dgrijalva/jwt-go"
)

// JWTExpiration defines how many seconds jwt token is valid
const JWTExpiration = 3600

func GenerateJWT(scope string, keyID string, secret string) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"scope": scope,
"exp": time.Now().Unix() + JWTExpiration,
})
token.Header = map[string]interface{}{
"alg": "HS256",
Expand All @@ -16,3 +22,38 @@ func GenerateJWT(scope string, keyID string, secret string) (string, error) {

return token.SignedString([]byte(secret))
}

// getJWTExpiration will get jwt expiration time
func getJWTExpiration(jwtToken string, secret string) (int64, error) {
claims := jwt.MapClaims{}

_, err := jwt.ParseWithClaims(jwtToken, &claims, func(t *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err != nil {
return -1, err
}

expiredIn := claims["exp"].(int64) - time.Now().Unix()
return expiredIn, nil
}

// isJWTExpired will check whether Smooch JWT is expired or not.
func isJWTExpired(jwtToken string, secret string) (bool, error) {
_, err := jwt.ParseWithClaims(jwtToken, jwt.MapClaims{}, func(t *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})

if err == nil {
return false, nil
}

switch err.(type) {
case *jwt.ValidationError:
vErr := err.(*jwt.ValidationError)
if vErr.Errors == jwt.ValidationErrorExpired {
return true, nil
}
}
return false, err
}
23 changes: 23 additions & 0 deletions pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## What does this PR do?
_Place what this pull request changes and anything affected. If your PR block or require another PR, also need to mention here_

## Why are we doing this? Any context or related work?
_You may put your JIRA card link here_

## Where should a reviewer start?
_optional -- if your changes affected so much files, it is encouraged to give helper for reviewer_

## Screenshots
_optional -- You may put the database, sequence or any diagram needed_

## Manual testing steps?
_Steps to do tests. including all possible that can hape_

## Database changes
_optional -- If there's database changes, put it here_

## Config changes
_optional -- If there's config changes, put it here_

## Deployment instructions
_optional -- Better to put it if there's some 'special case' for deployment_
Loading