Skip to content

Commit

Permalink
⚡️ Added LogOut http handler
Browse files Browse the repository at this point in the history
  • Loading branch information
lhbelfanti committed Jan 14, 2025
1 parent 207ea5e commit 4780989
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 11 deletions.
7 changes: 5 additions & 2 deletions cmd/api/auth/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ var (
)

const (
InvalidRequestBody = "Invalid request body"
FailedToSignUp = "Failed to sign up"
InvalidRequestBody = "Invalid request body"
FailedToSignUp = "Failed to sign up"
FailedToLogIn = "Failed to log in"
FailedToLogOut = "Failed to log out"
AuthorizationTokenRequired = "Authorization token is required"
)
34 changes: 29 additions & 5 deletions cmd/api/auth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/json"
"errors"
"net/http"

"ahbcc/cmd/api/user"
"ahbcc/internal/log"
)
Expand Down Expand Up @@ -42,8 +42,8 @@ func SignUpHandlerV1(signUp SignUp) http.HandlerFunc {
}
}

// LogInV1 HTTP Handler of the endpoint /auth/login/v1
func LogInV1(logIn LogIn) http.HandlerFunc {
// LogInHandlerV1 HTTP Handler of the endpoint /auth/login/v1
func LogInHandlerV1(logIn LogIn) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

Expand All @@ -67,10 +67,10 @@ func LogInV1(logIn LogIn) http.HandlerFunc {

switch {
case errors.Is(err, FailedToLoginDueWrongPassword):
http.Error(w, FailedToSignUp, http.StatusUnauthorized)
http.Error(w, FailedToLogIn, http.StatusUnauthorized)
return
default:
http.Error(w, FailedToSignUp, http.StatusInternalServerError)
http.Error(w, FailedToLogIn, http.StatusInternalServerError)
return
}
}
Expand All @@ -87,6 +87,30 @@ func LogInV1(logIn LogIn) http.HandlerFunc {
}
}

// LogOutHandlerV1 HTTP Handler of the endpoint /auth/logout/v1
func LogOutHandlerV1(logOut LogOut) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

token := r.Header.Get("X-Session-Token")
if token == "" {
log.Error(ctx, AuthorizationTokenRequired)
http.Error(w, AuthorizationTokenRequired, http.StatusUnauthorized)
return
}

err := logOut(ctx, token)
if err != nil {
log.Error(ctx, err.Error())
http.Error(w, FailedToLogOut, http.StatusInternalServerError)
}

log.Info(ctx, "User successfully logged out")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("User successfully logged out"))
}
}

// validateBody validates that mandatory fields are present
func validateBody(user user.DTO) error {
if user.Username == "" {
Expand Down
55 changes: 51 additions & 4 deletions cmd/api/auth/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func TestLoginHandlerV1_success(t *testing.T) {
mockBody, _ := json.Marshal(mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/login/v1", bytes.NewReader(mockBody))

logInHandlerV1 := auth.LogInV1(mockLogIn)
logInHandlerV1 := auth.LogInHandlerV1(mockLogIn)

logInHandlerV1(mockResponseWriter, mockRequest)

Expand All @@ -115,7 +115,7 @@ func TestLoginHandlerV1_failsWhenTheBodyCantBeParsed(t *testing.T) {
mockBody, _ := json.Marshal(`{"wrong": "body"}`)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/login/v1", bytes.NewReader(mockBody))

logInHandlerV1 := auth.LogInV1(mockLogIn)
logInHandlerV1 := auth.LogInHandlerV1(mockLogIn)

logInHandlerV1(mockResponseWriter, mockRequest)

Expand All @@ -139,7 +139,7 @@ func TestLoginHandlerV1_failsWhenValidateBodyThrowsError(t *testing.T) {
mockBody, _ := json.Marshal(test.mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/login/v1", bytes.NewReader(mockBody))

logInHandlerV1 := auth.LogInV1(mockLogIn)
logInHandlerV1 := auth.LogInHandlerV1(mockLogIn)

logInHandlerV1(mockResponseWriter, mockRequest)

Expand All @@ -164,7 +164,7 @@ func TestLoginHandlerV1_failsWhenLogInThrowsError(t *testing.T) {
mockBody, _ := json.Marshal(mockUser)
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/login/v1", bytes.NewReader(mockBody))

logInHandlerV1 := auth.LogInV1(mockLogIn)
logInHandlerV1 := auth.LogInHandlerV1(mockLogIn)

logInHandlerV1(mockResponseWriter, mockRequest)

Expand All @@ -175,3 +175,50 @@ func TestLoginHandlerV1_failsWhenLogInThrowsError(t *testing.T) {
}

}

func TestLogoutHandlerV1_success(t *testing.T) {
mockLogOut := auth.MockLogout(nil)
mockResponseWriter := httptest.NewRecorder()
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/logout/v1", nil)
mockRequest.Header.Set("X-Session-Token", "token")

logOutHandlerV1 := auth.LogOutHandlerV1(mockLogOut)

logOutHandlerV1(mockResponseWriter, mockRequest)

want := http.StatusOK
got := mockResponseWriter.Result().StatusCode

assert.Equal(t, want, got)
}

func TestLogoutHandlerV1_failsWhenSessionTokenHeaderWasNotFound(t *testing.T) {
mockLogOut := auth.MockLogout(nil)
mockResponseWriter := httptest.NewRecorder()
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/logout/v1", nil)

logOutHandlerV1 := auth.LogOutHandlerV1(mockLogOut)

logOutHandlerV1(mockResponseWriter, mockRequest)

want := http.StatusUnauthorized
got := mockResponseWriter.Result().StatusCode

assert.Equal(t, want, got)
}

func TestLogoutHandlerV1_failsWhenLogOutThrowsError(t *testing.T) {
mockLogOut := auth.MockLogout(errors.New("failed to logout"))
mockResponseWriter := httptest.NewRecorder()
mockRequest, _ := http.NewRequestWithContext(context.Background(), http.MethodPost, "/auth/logout/v1", nil)
mockRequest.Header.Set("X-Session-Token", "token")

logOutHandlerV1 := auth.LogOutHandlerV1(mockLogOut)

logOutHandlerV1(mockResponseWriter, mockRequest)

want := http.StatusInternalServerError
got := mockResponseWriter.Result().StatusCode

assert.Equal(t, want, got)
}
7 changes: 7 additions & 0 deletions cmd/api/auth/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ func MockLogIn(token string, expiresAt time.Time, err error) LogIn {
return token, expiresAt, err
}
}

// MockLogout mocks LogOut function
func MockLogout(err error) LogOut {
return func(ctx context.Context, user string) error {
return err
}
}

0 comments on commit 4780989

Please sign in to comment.