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

results matching ""

    No results matching ""