mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add Sign-out functionality (#46)
#37 implemented the Sign-_in_ flow, but there wasn't a Sign-_out_ flow as part of that PR (aside from letting the cookie expire... or manually deleting the cookie...), which is obviously not ideal. This PR implements a basic sign-out flow, along with a very simple user dropdown:  Bringing in a few pruned down components for the `<UserDropdown />` to integrate into the `<NavBar />`. In addition, this also implements a simple back-end API for `/logout` which just clears the session token.
This commit is contained in:
@@ -35,6 +35,7 @@ func New(options *Options) http.Handler {
|
||||
})
|
||||
})
|
||||
r.Post("/login", users.loginWithPassword)
|
||||
r.Post("/logout", users.logout)
|
||||
r.Route("/users", func(r chi.Router) {
|
||||
r.Post("/", users.createInitialUser)
|
||||
|
||||
|
||||
@@ -237,6 +237,20 @@ func (users *users) loginWithPassword(rw http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// Clear the user's session cookie
|
||||
func (*users) logout(rw http.ResponseWriter, r *http.Request) {
|
||||
// Get a blank token cookie
|
||||
cookie := &http.Cookie{
|
||||
// MaxAge < 0 means to delete the cookie now
|
||||
MaxAge: -1,
|
||||
Name: httpmw.AuthCookie,
|
||||
Path: "/",
|
||||
}
|
||||
|
||||
http.SetCookie(rw, cookie)
|
||||
render.Status(r, http.StatusOK)
|
||||
}
|
||||
|
||||
// Generates a new ID and secret for an API key.
|
||||
func generateAPIKeyIDSecret() (id string, secret string, err error) {
|
||||
// Length of an API Key ID.
|
||||
|
||||
@@ -2,12 +2,14 @@ package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/httpmw"
|
||||
)
|
||||
|
||||
func TestUsers(t *testing.T) {
|
||||
@@ -75,3 +77,30 @@ func TestUsers(t *testing.T) {
|
||||
require.Len(t, orgs, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLogout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("LogoutShouldClearCookie", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := coderdtest.New(t)
|
||||
fullURL, err := server.URL.Parse("/api/v2/logout")
|
||||
require.NoError(t, err, "Server URL should parse successfully")
|
||||
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, fullURL.String(), nil)
|
||||
require.NoError(t, err, "/logout request construction should succeed")
|
||||
|
||||
httpClient := &http.Client{}
|
||||
|
||||
response, err := httpClient.Do(req)
|
||||
require.NoError(t, err, "/logout request should succeed")
|
||||
response.Body.Close()
|
||||
|
||||
cookies := response.Cookies()
|
||||
require.Len(t, cookies, 1, "Exactly one cookie should be returned")
|
||||
|
||||
require.Equal(t, cookies[0].Name, httpmw.AuthCookie, "Cookie should be the auth cookie")
|
||||
require.Equal(t, cookies[0].MaxAge, -1, "Cookie should be set to delete")
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user