all repos

onasty @ 09a22a834f95a9c5a2c710c084cdb039c29283fb

a one-time notes service

onasty/e2e/apiv1_auth_test.go (view raw)

Smirnov Oleksandr Smirnov Oleksandr
ss2316544@gmail.com
feat: mailer service (#55)..., 1 year ago
1
package e2e_test
2
3
import (
4
	"net/http"
5
6
	"github.com/gofrs/uuid/v5"
7
	"github.com/olexsmir/onasty/internal/models"
8
)
9
10
type apiv1AuthSignUpRequest struct {
11
	Username string `json:"username"`
12
	Email    string `json:"email"`
13
	Password string `json:"password"`
14
}
15
16
func (e *AppTestSuite) TestAuthV1_SignUP() {
17
	username := "test" + e.uuid()
18
	email := e.uuid() + "test@test.com"
19
	password := "password"
20
21
	httpResp := e.httpRequest(
22
		http.MethodPost,
23
		"/api/v1/auth/signup",
24
		e.jsonify(apiv1AuthSignUpRequest{
25
			Username: username,
26
			Email:    email,
27
			Password: password,
28
		}),
29
	)
30
31
	dbUser := e.getUserFromDBByUsername(username)
32
	hashedPasswd, err := e.hasher.Hash(password)
33
	e.require.NoError(err)
34
35
	e.Equal(http.StatusCreated, httpResp.Code)
36
	e.Equal(dbUser.Email, email)
37
	e.Equal(dbUser.Password, hashedPasswd)
38
}
39
40
func (e *AppTestSuite) TestAuthV1_SignUP_badrequest() {
41
	tests := []struct {
42
		name     string
43
		username string
44
		email    string
45
		password string
46
	}{
47
		{name: "all fields empty", email: "", password: "", username: ""},
48
		{
49
			name:     "non valid email",
50
			username: "testing",
51
			email:    "email",
52
			password: "password",
53
		},
54
		{
55
			name:     "non valid password",
56
			email:    "test@test.com",
57
			password: "12345",
58
			username: "test",
59
		},
60
	}
61
	for _, t := range tests {
62
		httpResp := e.httpRequest(
63
			http.MethodPost,
64
			"/api/v1/auth/signup",
65
			e.jsonify(apiv1AuthSignUpRequest{
66
				Username: t.username,
67
				Email:    t.email,
68
				Password: t.password,
69
			}),
70
		)
71
72
		e.Equal(http.StatusBadRequest, httpResp.Code)
73
	}
74
}
75
76
type (
77
	apiv1AuthSignInRequest struct {
78
		Email    string `json:"email"`
79
		Password string `json:"password"`
80
	}
81
	apiv1AuthSignInResponse struct {
82
		AccessToken  string `json:"access_token"`
83
		RefreshToken string `json:"refresh_token"`
84
	}
85
)
86
87
func (e *AppTestSuite) TestAuthV1_VerifyEmail() {
88
	email := e.uuid() + "email@email.com"
89
	password := "qwerty"
90
91
	httpResp := e.httpRequest(
92
		http.MethodPost,
93
		"/api/v1/auth/signup",
94
		e.jsonify(apiv1AuthSignUpRequest{
95
			Username: e.uuid(),
96
			Email:    email,
97
			Password: password,
98
		}),
99
	)
100
101
	e.Equal(http.StatusCreated, httpResp.Code)
102
103
	user := e.getLastInsertedUserByEmail(email)
104
	token := e.getVerificationTokenByUserID(user.ID)
105
	httpResp = e.httpRequest(http.MethodGet, "/api/v1/auth/verify/"+token.Token, nil)
106
	e.Equal(http.StatusOK, httpResp.Code)
107
108
	user = e.getLastInsertedUserByEmail(email)
109
	e.Equal(user.Activated, true)
110
}
111
112
func (e *AppTestSuite) TestAuthV1_ResendVerificationEmail() {
113
	email, password := e.uuid()+"email@email.com", e.uuid()
114
115
	// create test user
116
	signUpHTTPResp := e.httpRequest(
117
		http.MethodPost,
118
		"/api/v1/auth/signup",
119
		e.jsonify(apiv1AuthSignUpRequest{
120
			Username: e.uuid(),
121
			Email:    email,
122
			Password: password,
123
		}),
124
	)
125
126
	e.Equal(http.StatusCreated, signUpHTTPResp.Code)
127
128
	// handle sending of the email
129
	httpResp := e.httpRequest(
130
		http.MethodPost,
131
		"/api/v1/auth/resend-verification-email",
132
		e.jsonify(apiv1AuthSignInRequest{
133
			Email:    email,
134
			Password: password,
135
		}),
136
	)
137
138
	e.Equal(http.StatusOK, httpResp.Code)
139
}
140
141
func (e *AppTestSuite) TestAuthV1_ResendVerificationEmail_wrong() {
142
	email, password := e.uuid()+"@"+e.uuid()+".com", "password"
143
	e.insertUserIntoDB(e.uuid(), email, password, true)
144
145
	tests := []struct {
146
		name         string
147
		email        string
148
		password     string
149
		expectedCode int
150
	}{
151
		{
152
			name:         "activated account",
153
			email:        email,
154
			password:     password,
155
			expectedCode: http.StatusBadRequest,
156
		},
157
		{
158
			name:         "wrong credentials",
159
			email:        email,
160
			password:     e.uuid(),
161
			expectedCode: http.StatusUnauthorized,
162
		},
163
	}
164
165
	for _, t := range tests {
166
		httpResp := e.httpRequest(
167
			http.MethodPost,
168
			"/api/v1/auth/resend-verification-email",
169
			e.jsonify(apiv1AuthSignInRequest{
170
				Email:    t.email,
171
				Password: t.password,
172
			}))
173
174
		e.Equal(httpResp.Code, t.expectedCode)
175
176
		// no email should be sent
177
		// e.Empty(e.mailer.GetLastSentEmailToEmail(t.email))
178
	}
179
}
180
181
func (e *AppTestSuite) TestAuthV1_SignIn() {
182
	email := e.uuid() + "email@email.com"
183
	password := "qwerty"
184
185
	uid := e.insertUserIntoDB("test", email, password, true)
186
187
	httpResp := e.httpRequest(
188
		http.MethodPost,
189
		"/api/v1/auth/signin",
190
		e.jsonify(apiv1AuthSignInRequest{
191
			Email:    email,
192
			Password: password,
193
		}),
194
	)
195
196
	var body apiv1AuthSignInResponse
197
	e.readBodyAndUnjsonify(httpResp.Body, &body)
198
199
	session := e.getLastUserSessionByUserID(uid)
200
	parsedToken := e.parseJwtToken(body.AccessToken)
201
202
	e.Equal(http.StatusOK, httpResp.Code)
203
	e.Equal(body.RefreshToken, session.RefreshToken)
204
	e.Equal(parsedToken.UserID, uid.String())
205
}
206
207
func (e *AppTestSuite) TestAuthV1_SignIn_wrong() {
208
	password := "password"
209
	email := e.uuid() + "@test.com"
210
	e.insertUserIntoDB(e.uuid(), email, "password", true)
211
212
	unactivatedEmail := e.uuid() + "@test.com"
213
	e.insertUserIntoDB(e.uuid(), unactivatedEmail, password, false)
214
215
	//exhaustruct:ignore
216
	tests := []struct {
217
		name         string
218
		email        string
219
		password     string
220
		expectedCode int
221
222
		expectMsg   bool
223
		expectedMsg string
224
	}{
225
		{
226
			name:         "unactivated user",
227
			email:        unactivatedEmail,
228
			password:     password,
229
			expectedCode: http.StatusBadRequest,
230
			expectMsg:    true,
231
			expectedMsg:  models.ErrUserIsNotActivated.Error(),
232
		},
233
		{
234
			name:         "wrong email",
235
			email:        "wrong@email.com",
236
			password:     password,
237
			expectedCode: http.StatusUnauthorized,
238
		},
239
		{
240
			name:         "wrong password",
241
			email:        email,
242
			password:     "wrong-wrong",
243
			expectedCode: http.StatusUnauthorized,
244
		},
245
	}
246
247
	for _, t := range tests {
248
		httpResp := e.httpRequest(
249
			http.MethodPost,
250
			"/api/v1/auth/signin",
251
			e.jsonify(apiv1AuthSignInRequest{
252
				Email:    t.email,
253
				Password: t.password,
254
			}),
255
		)
256
257
		if t.expectMsg {
258
			var body errorResponse
259
			e.readBodyAndUnjsonify(httpResp.Body, &body)
260
261
			e.Equal(body.Message, t.expectedMsg)
262
		}
263
264
		e.Equal(t.expectedCode, httpResp.Code)
265
	}
266
}
267
268
type apiv1AuthRefreshTokensRequest struct {
269
	RefreshToken string `json:"refresh_token"`
270
}
271
272
func (e *AppTestSuite) TestAuthV1_RefreshTokens() {
273
	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", e.uuid(), "password")
274
	httpResp := e.httpRequest(
275
		http.MethodPost,
276
		"/api/v1/auth/refresh-tokens",
277
		e.jsonify(apiv1AuthRefreshTokensRequest{
278
			RefreshToken: toks.RefreshToken,
279
		}),
280
	)
281
282
	var body apiv1AuthSignInResponse
283
	e.readBodyAndUnjsonify(httpResp.Body, &body)
284
285
	sessionDB := e.getLastUserSessionByUserID(uid)
286
	e.Equal(e.parseJwtToken(body.AccessToken).UserID, uid.String())
287
288
	e.Equal(httpResp.Code, http.StatusOK)
289
	e.NotEqual(toks.RefreshToken, body.RefreshToken)
290
	e.Equal(body.RefreshToken, sessionDB.RefreshToken)
291
}
292
293
func (e *AppTestSuite) TestAuthV1_RefreshTokens_wrong() {
294
	// requests a new token pair with a wrong refresh token
295
296
	httpResp := e.httpRequest(
297
		http.MethodPost,
298
		"/api/v1/auth/refresh-tokens",
299
		e.jsonify(apiv1AuthRefreshTokensRequest{
300
			RefreshToken: e.uuid(),
301
		}),
302
	)
303
304
	e.Equal(httpResp.Code, http.StatusBadRequest)
305
}
306
307
func (e *AppTestSuite) TestAuthV1_Logout() {
308
	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", e.uuid(), "password")
309
310
	sessionDB := e.getLastUserSessionByUserID(uid)
311
	e.NotEmpty(sessionDB.RefreshToken)
312
313
	httpResp := e.httpRequest(http.MethodPost, "/api/v1/auth/logout", nil, toks.AccessToken)
314
	e.Equal(httpResp.Code, http.StatusNoContent)
315
316
	sessionDB = e.getLastUserSessionByUserID(uid)
317
	e.Empty(sessionDB.RefreshToken)
318
}
319
320
type apiv1AtuhChangePasswordRequest struct {
321
	CurrentPassword string `json:"current_password"`
322
	NewPassword     string `json:"new_password"`
323
}
324
325
func (e *AppTestSuite) TestAuthV1_ChangePassword() {
326
	password := e.uuid()
327
	newPassword := e.uuid()
328
	username := e.uuid()
329
	_, toks := e.createAndSingIn(e.uuid()+"@test.com", username, password)
330
331
	httpResp := e.httpRequest(
332
		http.MethodPost,
333
		"/api/v1/auth/change-password",
334
		e.jsonify(apiv1AtuhChangePasswordRequest{
335
			CurrentPassword: password,
336
			NewPassword:     newPassword,
337
		}),
338
		toks.AccessToken,
339
	)
340
341
	e.Equal(httpResp.Code, http.StatusOK)
342
343
	userDB := e.getUserFromDBByUsername(username)
344
	hashedNewPassword, err := e.hasher.Hash(newPassword)
345
	e.require.NoError(err)
346
347
	e.Equal(userDB.Password, hashedNewPassword)
348
}
349
350
func (e *AppTestSuite) createAndSingIn(
351
	email, username, password string,
352
) (uuid.UUID, apiv1AuthSignInResponse) {
353
	uid := e.insertUserIntoDB(username, email, password, true)
354
	httpResp := e.httpRequest(
355
		http.MethodPost,
356
		"/api/v1/auth/signin",
357
		e.jsonify(apiv1AuthSignInRequest{
358
			Email:    email,
359
			Password: password,
360
		}),
361
	)
362
363
	e.Equal(httpResp.Code, http.StatusOK)
364
365
	var body apiv1AuthSignInResponse
366
	e.readBodyAndUnjsonify(httpResp.Body, &body)
367
368
	return uid, body
369
}