Implementing the Model
The isUserValid
function should return true
if the username/password combination passed in is valid. If not, it must return false
. We'll do this by going over the hardcoded list of users and matching the username/password combination, as follows:
// models.user.go
func isUserValid(username, password string) bool {
for _, u := range userList {
if u.Username == username && u.Password == password {
return true
}
}
return false
}
Now, run the following command in your shell to test that this function behaves as expected:
go test -run=TestUserValidity
This test should run successfully and show the following message:
PASS
ok github.com/demo-apps/go-gin-app 0.006s
Implementing the Route Handlers
The showLoginPage
handler is similar to the showRegistrationPage
handler from the previous section in that it displays a static page.
The performLogin
handler is largely similar to the register
handler with one notable exception. The performLogin
handler sets a cookie if the login is successful. Likewise, the logout
handler removes this cookie when a user logs out.
After implementing these handlers, handlers.user.go
should contain the following additional code:
// handlers.user.go
func showLoginPage(c *gin.Context) {
render(c, gin.H{
"title": "Login",
}, "login.html")
}
func performLogin(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
if isUserValid(username, password) {
token := generateSessionToken()
c.SetCookie("token", token, 3600, "", "", false, true)
render(c, gin.H{
"title": "Successful Login"}, "login-successful.html")
} else {
c.HTML(http.StatusBadRequest, "login.html", gin.H{
"ErrorTitle": "Login Failed",
"ErrorMessage": "Invalid credentials provided"})
}
}
func logout(c *gin.Context) {
c.SetCookie("token", "", -1, "", "", false, true)
c.Redirect(http.StatusTemporaryRedirect, "/")
}
With the handlers implemented, the tests should run successfully and result in the following output:
=== RUN TestShowIndexPageUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 269.85µs | | GET /
--- PASS: TestShowIndexPageUnauthenticated (0.00s)
=== RUN TestArticleUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 129.257µs | | GET /article/view/1
--- PASS: TestArticleUnauthenticated (0.00s)
=== RUN TestArticleListJSON
[GIN] 2016/09/04 - 09:16:54 | 200 | 38.957µs | | GET /
--- PASS: TestArticleListJSON (0.00s)
=== RUN TestArticleXML
[GIN] 2016/09/04 - 09:16:54 | 200 | 29.553µs | | GET /article/view/1
--- PASS: TestArticleXML (0.00s)
=== RUN TestShowRegistrationPageUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 114.762µs | | GET /u/register
--- PASS: TestShowRegistrationPageUnauthenticated (0.00s)
=== RUN TestRegisterUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 182.793µs | | POST /u/register
--- PASS: TestRegisterUnauthenticated (0.00s)
=== RUN TestRegisterUnauthenticatedUnavailableUsername
[GIN] 2016/09/04 - 09:16:54 | 400 | 160.118µs | | POST /u/register
--- PASS: TestRegisterUnauthenticatedUnavailableUsername (0.00s)
=== RUN TestShowLoginPageUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 101.494µs | | GET /u/login
--- PASS: TestShowLoginPageUnauthenticated (0.00s)
=== RUN TestLoginUnauthenticated
[GIN] 2016/09/04 - 09:16:54 | 200 | 91.377µs | | POST /u/login
--- PASS: TestLoginUnauthenticated (0.00s)
=== RUN TestLoginUnauthenticatedIncorrectCredentials
[GIN] 2016/09/04 - 09:16:54 | 400 | 110.563µs | | POST /u/login
--- PASS: TestLoginUnauthenticatedIncorrectCredentials (0.00s)
=== RUN TestGetAllArticles
--- PASS: TestGetAllArticles (0.00s)
=== RUN TestGetArticleByID
--- PASS: TestGetArticleByID (0.00s)
=== RUN TestValidUserRegistration
--- PASS: TestValidUserRegistration (0.00s)
=== RUN TestInvalidUserRegistration
--- PASS: TestInvalidUserRegistration (0.00s)
=== RUN TestUsernameAvailability
--- PASS: TestUsernameAvailability (0.00s)
=== RUN TestUserValidity
--- PASS: TestUserValidity (0.00s)
PASS
ok github.com/demo-apps/go-gin-app 0.010s