Compare commits
2 Commits
4708a2b8ff
...
c1ae0706f9
| Author | SHA1 | Date | |
|---|---|---|---|
|
c1ae0706f9
|
|||
|
8eff1115c5
|
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
github.com/golang-migrate/migrate/v4 v4.14.1
|
||||
github.com/jackc/pgx/v4 v4.10.1
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/lestrrat-go/jwx v1.0.6-0.20201127121120-26218808f029
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/stretchr/testify v1.5.1
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||
|
||||
@@ -2,57 +2,10 @@ package models_test
|
||||
|
||||
import (
|
||||
"gitea.deepak.science/deepak/gogmagog/models"
|
||||
"gitea.deepak.science/deepak/gogmagog/store"
|
||||
)
|
||||
|
||||
func (e *errorStore) SelectActions() ([]*models.Action, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectActionByID(id int) (*models.Action, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) InsertAction(action *models.Action) (int, error) {
|
||||
return 0, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) UpdateAction(action *models.Action) error {
|
||||
return e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectPlans() ([]*models.Plan, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectPlanByID(id int) (*models.Plan, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) InsertPlan(plan *models.Plan) (int, error) {
|
||||
return 0, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectActionsByPlanID(plan *models.Plan) ([]*models.Action, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectUserByUsername(username string) (*models.User, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) InsertUser(user *models.User) (int, error) {
|
||||
return 0, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) ConnectionLive() error {
|
||||
return e.error
|
||||
}
|
||||
|
||||
type errorStore struct {
|
||||
error error
|
||||
}
|
||||
|
||||
func getErrorModel(err error) *models.Model {
|
||||
e := &errorStore{error: err}
|
||||
return models.New(e)
|
||||
str := store.GetErrorStoreForError(err, true)
|
||||
return models.New(str)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestErrorModelWrapping(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
m := getErrorModel(sql.ErrNoRows)
|
||||
|
||||
_, err := m.Plan(0)
|
||||
_, err := m.Plan(0, 0)
|
||||
assert.True(models.IsNotFoundError(err))
|
||||
_, err = m.Action(0)
|
||||
assert.True(models.IsNotFoundError(err))
|
||||
|
||||
@@ -11,9 +11,9 @@ type Store interface {
|
||||
SelectActionByID(id int) (*Action, error)
|
||||
InsertAction(action *Action) (int, error)
|
||||
UpdateAction(action *Action) error
|
||||
SelectPlans() ([]*Plan, error)
|
||||
SelectPlanByID(id int) (*Plan, error)
|
||||
InsertPlan(plan *Plan) (int, error)
|
||||
SelectPlans(userID int) ([]*Plan, error)
|
||||
SelectPlanByID(id int, userID int) (*Plan, error)
|
||||
InsertPlan(plan *Plan, userID int) (int, error)
|
||||
SelectActionsByPlanID(plan *Plan) ([]*Action, error)
|
||||
SelectUserByUsername(username string) (*User, error)
|
||||
InsertUser(user *User) (int, error)
|
||||
|
||||
@@ -11,11 +11,12 @@ func TestModelActions(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
a1 := &models.Action{ActionID: 3}
|
||||
a2 := &models.Action{ActionID: 4}
|
||||
userID := 3
|
||||
p := &models.Plan{PlanID: 6}
|
||||
|
||||
str, _ := store.GetInMemoryStore()
|
||||
str.InsertAction(a1)
|
||||
str.InsertPlan(p)
|
||||
str.InsertPlan(p, userID)
|
||||
m := models.New(str)
|
||||
|
||||
actions, err := m.Actions()
|
||||
@@ -36,21 +37,22 @@ func TestModelActions(t *testing.T) {
|
||||
|
||||
func TestModelPlanMethods(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
userID := 3
|
||||
a1 := &models.Action{ActionID: 3, PlanID: 1}
|
||||
a2 := &models.Action{ActionID: 4}
|
||||
p := &models.Plan{}
|
||||
|
||||
str, _ := store.GetInMemoryStore()
|
||||
str.InsertPlan(p)
|
||||
str.InsertPlan(p, userID)
|
||||
str.InsertAction(a1)
|
||||
str.InsertAction(a2)
|
||||
m := models.New(str)
|
||||
|
||||
plans, err := m.Plans()
|
||||
plans, err := m.Plans(userID)
|
||||
assert.Nil(err)
|
||||
assert.Equal(1, len(plans))
|
||||
|
||||
firstPlan, err := m.Plan(1)
|
||||
firstPlan, err := m.Plan(1, userID)
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(1, firstPlan.PlanID)
|
||||
|
||||
@@ -58,7 +60,7 @@ func TestModelPlanMethods(t *testing.T) {
|
||||
assert.Nil(err)
|
||||
assert.Equal(1, len(actions))
|
||||
|
||||
planId, err := m.AddPlan(&models.Plan{})
|
||||
planId, err := m.AddPlan(&models.Plan{}, userID)
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(2, planId)
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@ type Plan struct {
|
||||
}
|
||||
|
||||
// Plans returns all plans in the model.
|
||||
func (m *Model) Plans() ([]*Plan, error) {
|
||||
return m.SelectPlans()
|
||||
func (m *Model) Plans(userID int) ([]*Plan, error) {
|
||||
return m.SelectPlans(userID)
|
||||
}
|
||||
|
||||
// Plan returns a single plan from the store by plan_id.
|
||||
func (m *Model) Plan(id int) (*Plan, error) {
|
||||
plan, err := m.SelectPlanByID(id)
|
||||
func (m *Model) Plan(id int, userID int) (*Plan, error) {
|
||||
plan, err := m.SelectPlanByID(id, userID)
|
||||
return plan, wrapNotFound(err)
|
||||
}
|
||||
|
||||
// AddPlan inserts a given plan into the store, returning the generated PlanID. The provided PlanID is ignored.
|
||||
func (m *Model) AddPlan(plan *Plan) (int, error) {
|
||||
return m.InsertPlan(plan)
|
||||
func (m *Model) AddPlan(plan *Plan, userID int) (int, error) {
|
||||
return m.InsertPlan(plan, userID)
|
||||
}
|
||||
|
||||
// GetActions returns the actions associated with a particular plan.
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestModelUsers(t *testing.T) {
|
||||
// password := password
|
||||
user1 := &models.User{Username: username, DisplayName: "Ted Est", Password: []byte("$2y$05$6SVV35GX4cB4PDPhRaDD/exsL.HV8QtMMr60YL6dLyqtX4l58q.cy")}
|
||||
str, _ := store.GetInMemoryStore()
|
||||
str.InsertPlan(p)
|
||||
str.InsertPlan(p, 3)
|
||||
str.InsertAction(a1)
|
||||
str.InsertAction(a2)
|
||||
str.InsertUser(user1)
|
||||
|
||||
@@ -3,8 +3,10 @@ package routes
|
||||
import (
|
||||
"encoding/json"
|
||||
"gitea.deepak.science/deepak/gogmagog/models"
|
||||
"gitea.deepak.science/deepak/gogmagog/tokens"
|
||||
"github.com/go-chi/chi"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
@@ -20,7 +22,14 @@ func NewPlanRouter(m *models.Model) http.Handler {
|
||||
|
||||
func getAllPlansFunc(m *models.Model) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
plans, err := m.Plans()
|
||||
userID, err := tokens.GetUserID(r.Context())
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
unauthorizedHandler(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
plans, err := m.Plans(userID)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
@@ -34,12 +43,20 @@ func getAllPlansFunc(m *models.Model) http.HandlerFunc {
|
||||
|
||||
func getPlanByIDFunc(m *models.Model) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID, err := tokens.GetUserID(r.Context())
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
unauthorizedHandler(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(chi.URLParam(r, "planid"))
|
||||
if err != nil {
|
||||
notFoundHandler(w, r)
|
||||
return
|
||||
}
|
||||
plan, err := m.Plan(id)
|
||||
// todo get real user id
|
||||
plan, err := m.Plan(id, userID)
|
||||
if err != nil {
|
||||
if models.IsNotFoundError(err) {
|
||||
notFoundHandler(w, r)
|
||||
@@ -63,12 +80,18 @@ type createPlanResponse struct {
|
||||
|
||||
func postPlanFunc(m *models.Model) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
userID, err := tokens.GetUserID(r.Context())
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
unauthorizedHandler(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 1024)
|
||||
dec := json.NewDecoder(r.Body)
|
||||
dec.DisallowUnknownFields()
|
||||
var p models.Plan
|
||||
err := dec.Decode(&p)
|
||||
err = dec.Decode(&p)
|
||||
if err != nil {
|
||||
badRequestError(w, err)
|
||||
return
|
||||
@@ -81,12 +104,12 @@ func postPlanFunc(m *models.Model) http.HandlerFunc {
|
||||
|
||||
// Map the fields we allow to be set to the plan to be created.
|
||||
plan := &models.Plan{PlanDate: p.PlanDate, UserID: p.UserID}
|
||||
id, err := m.AddPlan(plan)
|
||||
id, err := m.AddPlan(plan, userID)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
}
|
||||
plan, err = m.Plan(id)
|
||||
plan, err = m.Plan(id, userID)
|
||||
if err != nil {
|
||||
serverError(w, err)
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ package routes_test
|
||||
import (
|
||||
"gitea.deepak.science/deepak/gogmagog/models"
|
||||
"gitea.deepak.science/deepak/gogmagog/routes"
|
||||
"gitea.deepak.science/deepak/gogmagog/tokens"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -11,12 +12,14 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var sampleContext = tokens.GetContextForUserID(3)
|
||||
|
||||
func TestEmptyPlans(t *testing.T) {
|
||||
// set up
|
||||
assert := assert.New(t)
|
||||
m := getEmptyModel()
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -39,9 +42,9 @@ func TestOnePlan(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: 3}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -71,7 +74,7 @@ func TestErrorPlan(t *testing.T) {
|
||||
m := getErrorModel("Model always errors")
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -93,7 +96,7 @@ func TestEmptyPlanErrorWriter(t *testing.T) {
|
||||
m := getEmptyModel()
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/", nil)
|
||||
|
||||
rr := NewBadWriter()
|
||||
|
||||
@@ -112,9 +115,9 @@ func TestOnePlanByID(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: 3}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/1", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -142,7 +145,7 @@ func TestErrorPlanByID(t *testing.T) {
|
||||
m := getErrorModel("Model always errors")
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/5", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/5", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -164,10 +167,10 @@ func TestEmptyPlanErrorWriterByID(t *testing.T) {
|
||||
|
||||
p := &models.Plan{PlanID: 1, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/1", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
|
||||
|
||||
rr := NewBadWriter()
|
||||
|
||||
@@ -187,7 +190,7 @@ func TestNotFoundPlanByIDText(t *testing.T) {
|
||||
m := getEmptyModel()
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/wo", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/wo", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -206,7 +209,7 @@ func TestNotFoundPlanByIDEmpty(t *testing.T) {
|
||||
m := getEmptyModel()
|
||||
|
||||
router := routes.NewPlanRouter(m)
|
||||
req, _ := http.NewRequest("GET", "/1", nil)
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "GET", "/1", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestExtraFieldActionPostJSON(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewActionRouter(m)
|
||||
data := []byte(`{
|
||||
"completed_on": "2021-01-01T00:00:00Z",
|
||||
@@ -94,7 +94,7 @@ func TestEmptyBodyActionPost(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewActionRouter(m)
|
||||
data := []byte(``)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
@@ -118,7 +118,7 @@ func TestTwoBodyActionPost(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewActionRouter(m)
|
||||
data := []byte(`{
|
||||
"plan_id": 5
|
||||
|
||||
@@ -17,12 +17,13 @@ func TestCreatePlanRoute(t *testing.T) {
|
||||
// set up
|
||||
assert := assert.New(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: 3}
|
||||
userID := 3
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: int64(userID)}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, userID)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data, _ := json.Marshal(p)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -50,16 +51,17 @@ func TestPureJSON(t *testing.T) {
|
||||
// set up
|
||||
assert := assert.New(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 1, PlanDate: &planDate, UserID: 3}
|
||||
userID := 3
|
||||
p := &models.Plan{PlanID: 1, PlanDate: &planDate, UserID: int64(userID)}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, userID)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data := []byte(`{
|
||||
"plan_date": "2021-01-01T00:00:00Z",
|
||||
"plan_id": 1,
|
||||
"user_id": 3
|
||||
}`)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -87,16 +89,17 @@ func TestExtraFieldJSON(t *testing.T) {
|
||||
// set up
|
||||
assert := assert.New(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
userID := 3
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate, UserID: int64(userID)}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, userID)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data := []byte(`{
|
||||
"plan_date": "2021-01-01T00:00:00Z",
|
||||
"plan_id": 5,
|
||||
"plan_sabotage": "omg"
|
||||
}`)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -114,12 +117,13 @@ func TestEmptyBody(t *testing.T) {
|
||||
// set up
|
||||
assert := assert.New(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
userID := 3
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, userID)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data := []byte(``)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -140,7 +144,7 @@ func TestTwoBody(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data := []byte(`{
|
||||
"plan_date": "2021-01-01T00:00:00Z",
|
||||
@@ -149,7 +153,7 @@ func TestTwoBody(t *testing.T) {
|
||||
"plan_date": "2021-01-01T00:00:00Z",
|
||||
"plan_id": 6
|
||||
}`)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -174,7 +178,7 @@ func TestErrorCreatePlan(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
data, _ := json.Marshal(p)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -200,7 +204,7 @@ func TestErrorOnRetrieveCreatePlan(t *testing.T) {
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
data, _ := json.Marshal(p)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -222,10 +226,10 @@ func TestErrorWriterCreatePlan(t *testing.T) {
|
||||
|
||||
p := &models.Plan{PlanID: 6, PlanDate: &planDate}
|
||||
m := getEmptyModel()
|
||||
m.AddPlan(p)
|
||||
m.AddPlan(p, 3)
|
||||
router := routes.NewPlanRouter(m)
|
||||
data, _ := json.Marshal(p)
|
||||
req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(data))
|
||||
req, _ := http.NewRequestWithContext(sampleContext, "POST", "/", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
rr := NewBadWriter()
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"gitea.deepak.science/deepak/gogmagog/models"
|
||||
"gitea.deepak.science/deepak/gogmagog/tokens"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/jwtauth"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -15,12 +14,7 @@ func NewRouter(m *models.Model, tok tokens.Toker) http.Handler {
|
||||
router.MethodNotAllowed(methodNotAllowedHandler)
|
||||
router.NotFound(notFoundHandler)
|
||||
router.Group(func(r chi.Router) {
|
||||
r.Use(tok.Verifier())
|
||||
// Handle valid / invalid tokens. In this example, we use
|
||||
// the provided authenticator middleware, but you can write your
|
||||
// own very easily, look at the Authenticator method in jwtauth.go
|
||||
// and tweak it, its not scary.
|
||||
r.Use(jwtauth.Authenticator)
|
||||
r.Use(tok.Authenticator)
|
||||
r.Mount("/actions", NewActionRouter(m))
|
||||
r.Mount("/plans", NewPlanRouter(m))
|
||||
})
|
||||
|
||||
@@ -27,15 +27,15 @@ func (e *errorStore) UpdateAction(action *models.Action) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectPlans() ([]*models.Plan, error) {
|
||||
func (e *errorStore) SelectPlans(userID int) ([]*models.Plan, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) SelectPlanByID(id int) (*models.Plan, error) {
|
||||
func (e *errorStore) SelectPlanByID(id int, userID int) (*models.Plan, error) {
|
||||
return nil, e.error
|
||||
}
|
||||
|
||||
func (e *errorStore) InsertPlan(plan *models.Plan) (int, error) {
|
||||
func (e *errorStore) InsertPlan(plan *models.Plan, userID int) (int, error) {
|
||||
if e.errorOnInsert {
|
||||
return 0, e.error
|
||||
}
|
||||
@@ -66,8 +66,14 @@ type errorStore struct {
|
||||
errorOnInsert bool
|
||||
}
|
||||
|
||||
// GetErrorStore returns a models.Store that always errors. This is useful for testirng purposes.
|
||||
// GetErrorStore returns a models.Store that always errors. This is useful for testing purposes.
|
||||
func GetErrorStore(errorMsg string, errorOnInsert bool) models.Store {
|
||||
e := &errorStore{error: fmt.Errorf(errorMsg), errorOnInsert: errorOnInsert}
|
||||
return e
|
||||
}
|
||||
|
||||
// GetErrorStoreForError returns a models.Store that always errors with the provided error.
|
||||
func GetErrorStoreForError(err error, errorOnInsert bool) models.Store {
|
||||
e := &errorStore{error: err, errorOnInsert: errorOnInsert}
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -41,15 +41,15 @@ func TestErrorPlanMethods(t *testing.T) {
|
||||
str := store.GetErrorStore("sntahoeu", true)
|
||||
str2 := store.GetErrorStore("sntahoeu", false)
|
||||
|
||||
_, err := str.SelectPlans()
|
||||
_, err := str.SelectPlans(3)
|
||||
assert.NotNil(err)
|
||||
|
||||
_, err = str.InsertPlan(&models.Plan{})
|
||||
_, err = str.InsertPlan(&models.Plan{}, 3)
|
||||
assert.NotNil(err)
|
||||
_, err = str2.InsertPlan(&models.Plan{})
|
||||
_, err = str2.InsertPlan(&models.Plan{}, 3)
|
||||
assert.Nil(err)
|
||||
|
||||
_, err = str.SelectPlanByID(5)
|
||||
_, err = str.SelectPlanByID(5, 3)
|
||||
assert.NotNil(err)
|
||||
|
||||
}
|
||||
|
||||
@@ -64,22 +64,29 @@ func (store *inMemoryStore) UpdateAction(action *models.Action) error {
|
||||
|
||||
}
|
||||
|
||||
func (store *inMemoryStore) SelectPlans() ([]*models.Plan, error) {
|
||||
return store.plans, nil
|
||||
func (store *inMemoryStore) SelectPlans(userID int) ([]*models.Plan, error) {
|
||||
ret := make([]*models.Plan, 0)
|
||||
for _, plan := range store.plans {
|
||||
if int(plan.UserID) == userID {
|
||||
ret = append(ret, plan)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (store *inMemoryStore) SelectPlanByID(id int) (*models.Plan, error) {
|
||||
func (store *inMemoryStore) SelectPlanByID(id int, userID int) (*models.Plan, error) {
|
||||
for _, plan := range store.plans {
|
||||
if id == int(plan.PlanID) {
|
||||
if id == int(plan.PlanID) && (userID == int(plan.UserID)) {
|
||||
return plan, nil
|
||||
}
|
||||
}
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (store *inMemoryStore) InsertPlan(plan *models.Plan) (int, error) {
|
||||
func (store *inMemoryStore) InsertPlan(plan *models.Plan, userID int) (int, error) {
|
||||
id := len(store.plans) + 1
|
||||
plan.PlanID = int64(id)
|
||||
plan.UserID = int64(userID)
|
||||
store.plans = append(store.plans, plan)
|
||||
return id, nil
|
||||
}
|
||||
|
||||
@@ -55,24 +55,24 @@ func TestInMemoryActionMethods(t *testing.T) {
|
||||
func TestInMemoryPlanMethods(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
str, _ := store.GetInMemoryStore()
|
||||
|
||||
userID := 1
|
||||
p := &models.Plan{}
|
||||
plans, err := str.SelectPlans()
|
||||
plans, err := str.SelectPlans(userID)
|
||||
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(0, len(plans))
|
||||
|
||||
id, err := str.InsertPlan(p)
|
||||
plans, err = str.SelectPlans()
|
||||
id, err := str.InsertPlan(p, userID)
|
||||
plans, err = str.SelectPlans(userID)
|
||||
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(1, len(plans))
|
||||
|
||||
retrievedPlan, err := str.SelectPlanByID(id)
|
||||
retrievedPlan, err := str.SelectPlanByID(id, userID)
|
||||
assert.Nil(err)
|
||||
assert.Equal(retrievedPlan, p)
|
||||
|
||||
_, err = str.SelectPlanByID(135135)
|
||||
_, err = str.SelectPlanByID(135135, userID)
|
||||
assert.NotNil(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -97,29 +97,30 @@ func (store *postgresStore) UpdateAction(action *models.Action) error {
|
||||
|
||||
}
|
||||
|
||||
func (store *postgresStore) SelectPlans() ([]*models.Plan, error) {
|
||||
func (store *postgresStore) SelectPlans(userID int) ([]*models.Plan, error) {
|
||||
queryString := store.db.Rebind("SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = ?")
|
||||
plans := make([]*models.Plan, 0)
|
||||
err := store.db.Select(&plans, "SELECT plan_id, plan_date, user_id FROM plans")
|
||||
err := store.db.Select(&plans, queryString, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plans, nil
|
||||
}
|
||||
|
||||
func (store *postgresStore) SelectPlanByID(id int) (*models.Plan, error) {
|
||||
func (store *postgresStore) SelectPlanByID(id int, userID int) (*models.Plan, error) {
|
||||
plan := models.Plan{}
|
||||
err := store.db.Get(&plan, store.db.Rebind("SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = ?"), id)
|
||||
err := store.db.Get(&plan, store.db.Rebind("SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = ? AND user_id = ?"), id, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &plan, nil
|
||||
}
|
||||
|
||||
func (store *postgresStore) InsertPlan(plan *models.Plan) (int, error) {
|
||||
func (store *postgresStore) InsertPlan(plan *models.Plan, userID int) (int, error) {
|
||||
queryString := store.db.Rebind("INSERT INTO plans (plan_date, user_id) VALUES (?, ?) RETURNING plan_id")
|
||||
tx := store.db.MustBegin()
|
||||
var id int
|
||||
err := tx.Get(&id, queryString, plan.PlanDate, plan.UserID)
|
||||
err := tx.Get(&id, queryString, plan.PlanDate, userID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return -1, err
|
||||
|
||||
@@ -19,9 +19,11 @@ func TestSelectPlans(t *testing.T) {
|
||||
str, mock := getDbMock(t)
|
||||
|
||||
rows := sqlmock.NewRows([]string{"plan_id", "plan_date", "user_id"}).AddRow(idToUse, currentTime, userIDToUse)
|
||||
mock.ExpectQuery("^SELECT plan_id, plan_date, user_id FROM plans$").WillReturnRows(rows)
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = \$1`).
|
||||
WithArgs(userIDToUse).
|
||||
WillReturnRows(rows)
|
||||
|
||||
plans, err := str.SelectPlans()
|
||||
plans, err := str.SelectPlans(userIDToUse)
|
||||
assert.Nil(err)
|
||||
assert.Equal(1, len(plans))
|
||||
plan := plans[0]
|
||||
@@ -44,9 +46,11 @@ func TestSelectPlanByID(t *testing.T) {
|
||||
str, mock := getDbMock(t)
|
||||
|
||||
rows := sqlmock.NewRows([]string{"plan_id", "plan_date", "user_id"}).AddRow(idToUse, currentTime, userIDToUse)
|
||||
mock.ExpectQuery("^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \\$1$").WithArgs(idToUse).WillReturnRows(rows)
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
|
||||
WithArgs(idToUse, userIDToUse).
|
||||
WillReturnRows(rows)
|
||||
|
||||
plan, err := str.SelectPlanByID(idToUse)
|
||||
plan, err := str.SelectPlanByID(idToUse, userIDToUse)
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(idToUse, plan.PlanID)
|
||||
assert.Equal(currentTime, *plan.PlanDate)
|
||||
@@ -64,8 +68,9 @@ func TestInsertPlan(t *testing.T) {
|
||||
str, mock := getDbMock(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
userID := 2
|
||||
badUserID := 7
|
||||
|
||||
plan := &models.Plan{PlanDate: &planDate, UserID: int64(userID)}
|
||||
plan := &models.Plan{PlanDate: &planDate, UserID: int64(badUserID)}
|
||||
|
||||
idToUse := 8
|
||||
|
||||
@@ -78,7 +83,7 @@ func TestInsertPlan(t *testing.T) {
|
||||
mock.ExpectCommit()
|
||||
|
||||
// function under test
|
||||
insertedId, err := str.InsertPlan(plan)
|
||||
insertedId, err := str.InsertPlan(plan, userID)
|
||||
// check results
|
||||
assert.Nil(err)
|
||||
assert.EqualValues(idToUse, insertedId)
|
||||
@@ -95,7 +100,8 @@ func TestInsertPlanErr(t *testing.T) {
|
||||
str, mock := getDbMock(t)
|
||||
planDate, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
userID := 2
|
||||
plan := &models.Plan{PlanDate: &planDate, UserID: 2}
|
||||
badUserID := 7
|
||||
plan := &models.Plan{PlanDate: &planDate, UserID: int64(badUserID)}
|
||||
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectQuery(`^INSERT INTO plans \(plan_date, user_id\) VALUES \(\$1, \$2\) RETURNING plan_id$`).
|
||||
@@ -104,7 +110,7 @@ func TestInsertPlanErr(t *testing.T) {
|
||||
mock.ExpectRollback()
|
||||
|
||||
// function under test
|
||||
_, err := str.InsertPlan(plan)
|
||||
_, err := str.InsertPlan(plan, userID)
|
||||
// check results
|
||||
assert.NotNil(err)
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
@@ -132,7 +138,7 @@ func TestInsertPlanCommitErr(t *testing.T) {
|
||||
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
|
||||
|
||||
// function under test
|
||||
_, err := str.InsertPlan(plan)
|
||||
_, err := str.InsertPlan(plan, userID)
|
||||
// check results
|
||||
assert.NotNil(err)
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
@@ -148,9 +154,11 @@ func TestErrPlanByID(t *testing.T) {
|
||||
|
||||
str, mock := getDbMock(t)
|
||||
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \$1$`).WithArgs(idToUse).WillReturnError(fmt.Errorf("example error"))
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE plan_id = \$1 AND user_id = \$2$`).
|
||||
WithArgs(idToUse, 8).
|
||||
WillReturnError(fmt.Errorf("example error"))
|
||||
|
||||
plan, err := str.SelectPlanByID(idToUse)
|
||||
plan, err := str.SelectPlanByID(idToUse, 8)
|
||||
assert.NotNil(err)
|
||||
assert.Nil(plan)
|
||||
|
||||
@@ -164,9 +172,11 @@ func TestErrPlans(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
str, mock := getDbMock(t)
|
||||
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans$`).WillReturnError(fmt.Errorf("example error"))
|
||||
mock.ExpectQuery(`^SELECT plan_id, plan_date, user_id FROM plans WHERE user_id = \$1$`).
|
||||
WithArgs(8).
|
||||
WillReturnError(fmt.Errorf("example error"))
|
||||
// function under test
|
||||
plans, err := str.SelectPlans()
|
||||
plans, err := str.SelectPlans(8)
|
||||
// test results
|
||||
assert.Nil(plans)
|
||||
assert.NotNil(err)
|
||||
|
||||
71
tokens/middleware.go
Normal file
71
tokens/middleware.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package tokens
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type contextKey struct {
|
||||
name string
|
||||
}
|
||||
|
||||
var userIDCtxKey = &contextKey{"UserID"}
|
||||
|
||||
func unauthorized(w http.ResponseWriter, r *http.Request) {
|
||||
code := http.StatusUnauthorized
|
||||
http.Error(w, http.StatusText(code), code)
|
||||
}
|
||||
|
||||
// TokenFromHeader tries to retreive the token string from the
|
||||
// "Authorization" reqeust header: "Authorization: BEARER T".
|
||||
func TokenFromHeader(r *http.Request) string {
|
||||
// Get token from authorization header.
|
||||
bearer := r.Header.Get("Authorization")
|
||||
if len(bearer) > 7 && strings.ToUpper(bearer[0:6]) == "BEARER" {
|
||||
return bearer[7:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (tok *jwtToker) Authenticator(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
tokenString := TokenFromHeader(r)
|
||||
if tokenString == "" {
|
||||
log.Print("No valid token found")
|
||||
unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
userID, err := tok.DecodeTokenString(tokenString)
|
||||
if err != nil {
|
||||
log.Printf("Error while verifying token: %s", err)
|
||||
unauthorized(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Got user with ID: [%d]", userID)
|
||||
ctx := context.WithValue(r.Context(), userIDCtxKey, userID)
|
||||
// Authenticated
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// GetUserID is a convenience method that gets the user ID from the context.
|
||||
// I hate the fact that we're passing user ID on the context, but it is more
|
||||
// idiomatic Go than any type shenanigans.
|
||||
func GetUserID(ctx context.Context) (int, error) {
|
||||
userID, ok := ctx.Value(userIDCtxKey).(int64)
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("Could not parse user ID [%s] from context", ctx.Value(userIDCtxKey))
|
||||
|
||||
}
|
||||
return int(userID), nil
|
||||
}
|
||||
|
||||
// GetContextForUserID is a test helper method that creates a context with user ID set.
|
||||
func GetContextForUserID(userID int) context.Context {
|
||||
return context.WithValue(context.Background(), userIDCtxKey, int64(userID))
|
||||
}
|
||||
56
tokens/middleware_test.go
Normal file
56
tokens/middleware_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package tokens_test
|
||||
|
||||
import (
|
||||
"gitea.deepak.science/deepak/gogmagog/tokens"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
url = ""
|
||||
authKey = "Authorization"
|
||||
)
|
||||
|
||||
func requestWithAuth(header string) *http.Request {
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Add(authKey, header)
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func TestHeaderParseBasic(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
header := "Bearer testing"
|
||||
req := requestWithAuth(header)
|
||||
|
||||
assert.Equal("testing", tokens.TokenFromHeader(req))
|
||||
}
|
||||
|
||||
func TestHeaderParseNoSpace(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
header := "Bearerxtesting"
|
||||
req := requestWithAuth(header)
|
||||
|
||||
assert.Equal("testing", tokens.TokenFromHeader(req))
|
||||
}
|
||||
|
||||
func TestHeaderParseUnicode(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
header := "Bearer 🌸"
|
||||
req := requestWithAuth(header)
|
||||
|
||||
assert.Equal("🌸", tokens.TokenFromHeader(req))
|
||||
}
|
||||
|
||||
func TestHeaderParseMalformed(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
header := "testing"
|
||||
req := requestWithAuth(header)
|
||||
|
||||
assert.Equal("", tokens.TokenFromHeader(req))
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package tokens
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.deepak.science/deepak/gogmagog/models"
|
||||
"github.com/go-chi/jwtauth"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@@ -10,8 +12,8 @@ import (
|
||||
// Toker represents a tokenizer, capable of encoding and verifying tokens.
|
||||
type Toker interface {
|
||||
EncodeUser(user *models.UserNoPassword) string
|
||||
VerifyTokenString(tokenString string) error
|
||||
Verifier() func(http.Handler) http.Handler
|
||||
DecodeTokenString(tokenString string) (int64, error)
|
||||
Authenticator(http.Handler) http.Handler
|
||||
}
|
||||
|
||||
type jwtToker struct {
|
||||
@@ -37,11 +39,32 @@ func (tok *jwtToker) EncodeUser(user *models.UserNoPassword) string {
|
||||
return tokenString
|
||||
}
|
||||
|
||||
func (tok *jwtToker) VerifyTokenString(tokenString string) error {
|
||||
_, err := jwtauth.VerifyToken(tok.tokenAuth, tokenString)
|
||||
return err
|
||||
}
|
||||
func (tok *jwtToker) DecodeTokenString(tokenString string) (int64, error) {
|
||||
token, err := tok.tokenAuth.Decode(tokenString)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("Error decoding token")
|
||||
}
|
||||
|
||||
func (tok *jwtToker) Verifier() func(http.Handler) http.Handler {
|
||||
return jwtauth.Verifier(tok.tokenAuth)
|
||||
if token == nil {
|
||||
return -1, fmt.Errorf("Token was nil")
|
||||
}
|
||||
|
||||
err = jwt.Validate(
|
||||
token,
|
||||
jwt.WithIssuer("gogmagog.deepak.science"),
|
||||
jwt.WithAudience("gogmagog.deepak.science"),
|
||||
)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
userIDRaw, ok := token.Get("user_id")
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("error finding user_id claim")
|
||||
}
|
||||
userID, ok := userIDRaw.(float64)
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("Could not parse [%s] as userID", userIDRaw)
|
||||
}
|
||||
return int64(userID), nil
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ func TestBasic(t *testing.T) {
|
||||
}
|
||||
token := toker.EncodeUser(usr)
|
||||
|
||||
assert.Nil(toker.VerifyTokenString(token))
|
||||
assert.NotNil(tokens.New("bad secret").VerifyTokenString(token))
|
||||
_, err := toker.DecodeTokenString(token)
|
||||
assert.Nil(err)
|
||||
_, err = tokens.New("bad secret").DecodeTokenString(token)
|
||||
assert.NotNil(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user