Skip to content

Commit 60e4759

Browse files
Add scaffolding for testing http endpoints
1 parent 5838d64 commit 60e4759

File tree

11 files changed

+175
-136
lines changed

11 files changed

+175
-136
lines changed

actions/auth.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,6 @@ func PostSignup(c *gin.Context) {
156156
}
157157
}
158158

159-
uuid, err := uuid.NewRandom()
160-
if err != nil {
161-
logger.From(c).WithError(err).Error("Unable to generate random uuid.")
162-
c.JSON(http.StatusForbidden, gin.H{
163-
"message": "Unable to create an account.",
164-
})
165-
return
166-
}
167-
168159
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(body.Password), bcrypt.DefaultCost)
169160
if err != nil {
170161
logger.From(c).WithError(err).Error("Unable to generate hash from password.")
@@ -174,6 +165,8 @@ func PostSignup(c *gin.Context) {
174165
return
175166
}
176167

168+
uuid := uuid.New()
169+
177170
user := &entities.User{
178171
Username: body.Email,
179172
UUID: uuid.String(),
@@ -574,12 +567,7 @@ func completeCallback(c *gin.Context, email, source, host string) {
574567
return
575568
}
576569

577-
uuid, err := uuid.NewRandom()
578-
if err != nil {
579-
logger.From(c).WithError(err).Error("Unable to generate random uuid.")
580-
c.Redirect(http.StatusPermanentRedirect, host+"/login?message=register-failed")
581-
return
582-
}
570+
uuid := uuid.New()
583571

584572
u = &entities.User{
585573
UUID: uuid.String(),

actions/setup_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package actions_test
2+
3+
import (
4+
"database/sql"
5+
"net/http"
6+
"os"
7+
"strconv"
8+
"testing"
9+
10+
"github.com/mailbadger/app/entities"
11+
"github.com/mailbadger/app/entities/params"
12+
"golang.org/x/crypto/bcrypt"
13+
14+
"github.com/gavv/httpexpect/v2"
15+
"github.com/gin-contrib/sessions"
16+
"github.com/gin-contrib/sessions/cookie"
17+
"github.com/gin-gonic/gin"
18+
"github.com/mailbadger/app/routes"
19+
"github.com/mailbadger/app/routes/middleware"
20+
"github.com/mailbadger/app/storage"
21+
)
22+
23+
func init() {
24+
gin.SetMode(gin.TestMode)
25+
}
26+
27+
func setup(t *testing.T, s storage.Storage) *httpexpect.Expect {
28+
err := os.Setenv("SESSION_AUTH_KEY", "foo")
29+
if err != nil {
30+
t.FailNow()
31+
}
32+
err = os.Setenv("SESSION_ENCRYPT_KEY", "secretexmplkeythatis32characters")
33+
if err != nil {
34+
t.FailNow()
35+
}
36+
37+
cookiestore := cookie.NewStore(
38+
[]byte(os.Getenv("SESSION_AUTH_KEY")),
39+
[]byte(os.Getenv("SESSION_ENCRYPT_KEY")),
40+
)
41+
secureCookie, _ := strconv.ParseBool(os.Getenv("SECURE_COOKIE"))
42+
cookiestore.Options(sessions.Options{
43+
Secure: secureCookie,
44+
HttpOnly: true,
45+
})
46+
47+
handler := gin.New()
48+
handler.Use(sessions.Sessions("mbsess", cookiestore))
49+
handler.Use(middleware.Storage(s))
50+
handler.Use(middleware.SetUser())
51+
52+
routes.SetGuestRoutes(handler)
53+
routes.SetAuthorizedRoutes(handler)
54+
55+
return httpexpect.WithConfig(httpexpect.Config{
56+
Client: &http.Client{
57+
Transport: httpexpect.NewBinder(handler),
58+
Jar: httpexpect.NewJar(),
59+
},
60+
Reporter: httpexpect.NewAssertReporter(t),
61+
Printers: []httpexpect.Printer{
62+
httpexpect.NewDebugPrinter(t, true),
63+
},
64+
})
65+
}
66+
67+
func createAuthenticatedExpect(e *httpexpect.Expect, s storage.Storage) (*httpexpect.Expect, error) {
68+
pass, err := bcrypt.GenerateFromPassword([]byte("hunter1"), bcrypt.DefaultCost)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
u := &entities.User{
74+
Active: true,
75+
Username: "john",
76+
Password: sql.NullString{
77+
String: string(pass),
78+
Valid: true,
79+
},
80+
}
81+
err = s.CreateUser(u)
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
c := e.POST("/api/authenticate").WithForm(params.PostAuthenticate{
87+
Username: "john",
88+
Password: "hunter1",
89+
}).Expect().Status(http.StatusOK).Cookie("mbsess")
90+
91+
return e.Builder(func(req *httpexpect.Request) {
92+
req.WithCookie(c.Name().Raw(), c.Value().Raw())
93+
}), nil
94+
}

actions/users_test.go

Lines changed: 12 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,30 @@ package actions_test
22

33
import (
44
"net/http"
5-
"os"
6-
"strconv"
75
"testing"
86

9-
"github.com/gin-contrib/sessions"
10-
"github.com/gin-contrib/sessions/cookie"
11-
"github.com/mailbadger/app/actions"
12-
"github.com/mailbadger/app/routes/middleware"
13-
14-
"github.com/gavv/httpexpect/v2"
15-
"github.com/gin-gonic/gin"
7+
"github.com/mailbadger/app/storage"
168
)
179

18-
func init() {
19-
gin.SetMode(gin.TestMode)
20-
}
10+
func TestUser(t *testing.T) {
11+
s := storage.New("sqlite3", ":memory:")
2112

22-
func TestUnauthorizedUser(t *testing.T) {
23-
err := os.Setenv("DATABASE_DRIVER", "sqlite3")
24-
if err != nil {
25-
t.FailNow()
26-
}
27-
err = os.Setenv("DATABASE_CONFIG", ":memory:")
28-
if err != nil {
29-
t.FailNow()
30-
}
31-
err = os.Setenv("SESSION_AUTH_KEY", "foo")
13+
e := setup(t, s)
14+
auth, err := createAuthenticatedExpect(e, s)
3215
if err != nil {
16+
t.Error(err)
3317
t.FailNow()
3418
}
35-
err = os.Setenv("SESSION_AUTH_KEY", "secretexmplkeythatis32characters")
36-
if err != nil {
37-
t.FailNow()
38-
}
39-
40-
store := cookie.NewStore(
41-
[]byte(os.Getenv("SESSION_AUTH_KEY")),
42-
[]byte(os.Getenv("SESSION_ENCRYPT_KEY")),
43-
)
44-
secureCookie, _ := strconv.ParseBool(os.Getenv("SECURE_COOKIE"))
45-
store.Options(sessions.Options{
46-
Secure: secureCookie,
47-
HttpOnly: true,
48-
})
49-
50-
handler := gin.New()
51-
handler.Use(sessions.Sessions("mbsess", store))
52-
handler.Use(middleware.Storage())
53-
handler.Use(middleware.SetUser())
54-
55-
authorized := handler.Group("/api")
56-
authorized.Use(middleware.Authorized())
57-
{
58-
users := authorized.Group("/users")
59-
{
60-
users.GET("/me", actions.GetMe)
61-
users.POST("/password", actions.ChangePassword)
62-
}
63-
}
64-
e := httpexpect.WithConfig(httpexpect.Config{
65-
Client: &http.Client{
66-
Transport: httpexpect.NewBinder(handler),
67-
Jar: httpexpect.NewJar(),
68-
},
69-
Reporter: httpexpect.NewAssertReporter(t),
70-
Printers: []httpexpect.Printer{
71-
httpexpect.NewDebugPrinter(t, true),
72-
},
73-
})
7419

7520
e.GET("/api/users/me").
7621
Expect().
7722
Status(http.StatusUnauthorized).
7823
JSON().Object().ValueEqual("message", "User not authorized")
7924

25+
auth.GET("/api/users/me").
26+
Expect().
27+
Status(http.StatusOK).
28+
JSON().Object().
29+
ValueEqual("username", "john").
30+
ValueEqual("active", true)
8031
}

consumers/campaigner/main.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,6 @@ func (h *MessageHandler) HandleMessage(m *nsq.Message) error {
124124
dest = append(dest, d)
125125
}
126126

127-
uuid, err := uuid.NewRandom()
128-
if err != nil {
129-
logrus.WithError(err).Error("Unable to generate random uuid.")
130-
continue
131-
}
132-
133127
defaultData, err := json.Marshal(msg.TemplateData)
134128
if err != nil {
135129
logrus.WithError(err).Error("Unable to marshal template data as JSON.")
@@ -158,6 +152,8 @@ func (h *MessageHandler) HandleMessage(m *nsq.Message) error {
158152
input.ConfigurationSetName = aws.String(emails.ConfigurationSetName)
159153
}
160154

155+
uuid := uuid.New()
156+
161157
bulkMsg := entities.BulkSendMessage{
162158
UUID: uuid.String(),
163159
Input: input,

dashboard/src/Templates/List.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ const List = () => {
148148
let table = null;
149149
if (state.isLoading) {
150150
table = <PlaceholderTable header={Header} numCols={4} numRows={5} />;
151-
} else if (state.data.collection.length > 0) {
151+
} else if (!state.isError && state.data.collection.length > 0) {
152152
table = (
153153
<TemplateTable
154154
isLoading={state.isLoading}
@@ -192,13 +192,13 @@ const List = () => {
192192
<Box animation="fadeIn">
193193
{table}
194194

195-
{!state.isLoading && state.data.collection.length === 0 ? (
195+
{!state.isLoading && !state.isError && state.data.collection.length === 0 ? (
196196
<Box align="center" margin={{ top: "large" }}>
197197
<Heading level="2">Create your first template.</Heading>
198198
</Box>
199199
) : null}
200200
</Box>
201-
{!state.isLoading && state.data.collection.length > 0 ? (
201+
{!state.isLoading && !state.isError && state.data.collection.length > 0 ? (
202202
<Box direction="row" alignSelf="end" margin={{ top: "medium" }}>
203203
<Box margin={{ right: "small" }}>
204204
<Button

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ github.com/aws/aws-sdk-go v1.27.0 h1:0xphMHGMLBrPMfxR2AmVjZKcMEESEgWF8Kru94BNByk
6969
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
7070
github.com/aws/aws-sdk-go v1.35.7 h1:FHMhVhyc/9jljgFAcGkQDYjpC9btM0B8VfkLBfctdNE=
7171
github.com/aws/aws-sdk-go v1.35.7/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
72+
github.com/aws/aws-sdk-go v1.35.9 h1:b1HiUpdkFLJyoOQ7zas36YHzjNHH0ivHx/G5lWBeg+U=
7273
github.com/aws/aws-sdk-go v1.35.9/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
7374
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
7475
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=

logger/logger.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ const key = "logger"
1111

1212
// From returns a logger entry from the given context.
1313
func From(ctx context.Context) *logrus.Entry {
14+
l := ctx.Value(key)
15+
if l == nil {
16+
return logrus.NewEntry(logrus.StandardLogger())
17+
}
1418
return ctx.Value(key).(*logrus.Entry)
1519
}
1620

routes/middleware/requestid.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package middleware
22

33
import (
44
"context"
5-
"net/http"
65

76
"github.com/gin-gonic/gin"
87
"github.com/google/uuid"
9-
"github.com/sirupsen/logrus"
108
)
119

1210
const reqIDKey = "reqid"
@@ -18,14 +16,7 @@ func RequestID() gin.HandlerFunc {
1816
requestID := c.Request.Header.Get("X-Request-Id")
1917

2018
if requestID == "" {
21-
uuid4, err := uuid.NewRandom()
22-
if err != nil {
23-
logrus.WithError(err).Error("RequestID: Unable to generate uuid")
24-
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
25-
"message": "We are unable to process the request at the moment. Please try again.",
26-
})
27-
return
28-
}
19+
uuid4 := uuid.New()
2920
requestID = uuid4.String()
3021
}
3122

routes/middleware/storage.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
package middleware
22

33
import (
4-
"os"
5-
64
"github.com/gin-gonic/gin"
75
"github.com/mailbadger/app/storage"
86
)
97

108
// Storage is a middleware that inits the Storage and attaches it to the context.
11-
func Storage() gin.HandlerFunc {
12-
driver := os.Getenv("DATABASE_DRIVER")
13-
config := storage.MakeConfigFromEnv(driver)
14-
s := storage.New(driver, config)
15-
9+
func Storage(s storage.Storage) gin.HandlerFunc {
1610
return func(c *gin.Context) {
1711
storage.SetToContext(c, s)
1812
c.Next()

0 commit comments

Comments
 (0)