316 lines
8.5 KiB
Go
316 lines
8.5 KiB
Go
package rest_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dwysokinski.me/twhelp/sessions/internal/domain"
|
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/mock"
|
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/model"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestSession_createOrUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now()
|
|
apiKey := uuid.NewString()
|
|
tests := []struct {
|
|
name string
|
|
setup func(*mock.FakeAPIKeyVerifier, *mock.FakeSessionService)
|
|
apiKey string
|
|
serverKey string
|
|
sid string
|
|
expectedStatus int
|
|
target any
|
|
expectedResponse any
|
|
}{
|
|
{
|
|
name: "OK",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
sessionSvc.CreateOrUpdateReturns(domain.Session{}, nil)
|
|
},
|
|
apiKey: apiKey,
|
|
serverKey: "pl151",
|
|
sid: base64.StdEncoding.EncodeToString([]byte(uuid.NewString())),
|
|
expectedStatus: http.StatusNoContent,
|
|
},
|
|
{
|
|
name: "ERR: len(serverKey) > 10",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
},
|
|
apiKey: apiKey,
|
|
serverKey: "012345678890",
|
|
sid: base64.StdEncoding.EncodeToString([]byte(uuid.NewString())),
|
|
expectedStatus: http.StatusBadRequest,
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: domain.ErrorCodeValidationError.String(),
|
|
Message: "ServerKey: the length must be no more than 10",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: SID is required",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
},
|
|
apiKey: apiKey,
|
|
serverKey: "pl151",
|
|
sid: "",
|
|
expectedStatus: http.StatusBadRequest,
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: domain.ErrorCodeValidationError.String(),
|
|
Message: "SID: cannot be blank",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: SID is not a valid base64",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
},
|
|
apiKey: apiKey,
|
|
serverKey: "pl151",
|
|
sid: uuid.NewString(),
|
|
expectedStatus: http.StatusBadRequest,
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: domain.ErrorCodeValidationError.String(),
|
|
Message: "SID: must be encoded in Base64",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: apiKey == \"\"",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {},
|
|
apiKey: "",
|
|
expectedStatus: http.StatusUnauthorized,
|
|
serverKey: "pl151",
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: "unauthorized",
|
|
Message: "invalid API key",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: unexpected API key",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyCalls(func(ctx context.Context, key string) (domain.User, error) {
|
|
if key != apiKey {
|
|
return domain.User{}, domain.APIKeyNotFoundError{
|
|
Key: key,
|
|
}
|
|
}
|
|
|
|
return domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil
|
|
})
|
|
},
|
|
apiKey: uuid.NewString(),
|
|
serverKey: "pl151",
|
|
expectedStatus: http.StatusUnauthorized,
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: "unauthorized",
|
|
Message: "invalid API key",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
apiKeySvc := &mock.FakeAPIKeyVerifier{}
|
|
sessionSvc := &mock.FakeSessionService{}
|
|
tt.setup(apiKeySvc, sessionSvc)
|
|
|
|
router := newRouter(withAPIKeyVerifier(apiKeySvc), withSessionService(sessionSvc))
|
|
|
|
resp := doRequest(
|
|
router,
|
|
http.MethodPut,
|
|
"/v1/user/sessions/"+tt.serverKey,
|
|
tt.apiKey,
|
|
strings.NewReader(tt.sid),
|
|
)
|
|
defer resp.Body.Close()
|
|
if tt.expectedStatus == http.StatusNoContent {
|
|
assert.Equal(t, tt.expectedStatus, resp.StatusCode)
|
|
return
|
|
}
|
|
assertJSONResponse(t, resp, tt.expectedStatus, tt.expectedResponse, tt.target)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSession_getCurrentUser(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now()
|
|
apiKey := uuid.NewString()
|
|
sid := base64.StdEncoding.EncodeToString([]byte(uuid.NewString()))
|
|
tests := []struct {
|
|
name string
|
|
setup func(*mock.FakeAPIKeyVerifier, *mock.FakeSessionService)
|
|
apiKey string
|
|
serverKey string
|
|
expectedStatus int
|
|
target any
|
|
expectedResponse any
|
|
}{
|
|
{
|
|
name: "OK",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
sessionSvc.GetCalls(func(ctx context.Context, userID int64, serverKey string) (domain.Session, error) {
|
|
return domain.Session{
|
|
ID: 111,
|
|
UserID: userID,
|
|
ServerKey: serverKey,
|
|
SID: sid,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}, nil
|
|
})
|
|
},
|
|
apiKey: apiKey,
|
|
serverKey: "pl151",
|
|
expectedStatus: http.StatusOK,
|
|
target: &model.GetSessionResp{},
|
|
expectedResponse: &model.GetSessionResp{
|
|
Data: model.Session{
|
|
ServerKey: "pl151",
|
|
SID: sid,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: session not found",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyReturns(domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil)
|
|
sessionSvc.GetCalls(func(ctx context.Context, userID int64, serverKey string) (domain.Session, error) {
|
|
return domain.Session{}, domain.SessionNotFoundError{
|
|
ServerKey: serverKey,
|
|
}
|
|
})
|
|
},
|
|
apiKey: apiKey,
|
|
expectedStatus: http.StatusNotFound,
|
|
serverKey: "pl151",
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: domain.ErrorCodeEntityNotFound.String(),
|
|
Message: "session (ServerKey=pl151) not found",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: apiKey == \"\"",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {},
|
|
apiKey: "",
|
|
expectedStatus: http.StatusUnauthorized,
|
|
serverKey: "pl151",
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: "unauthorized",
|
|
Message: "invalid API key",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "ERR: unexpected API key",
|
|
setup: func(apiKeySvc *mock.FakeAPIKeyVerifier, sessionSvc *mock.FakeSessionService) {
|
|
apiKeySvc.VerifyCalls(func(ctx context.Context, key string) (domain.User, error) {
|
|
if key != apiKey {
|
|
return domain.User{}, domain.APIKeyNotFoundError{
|
|
Key: key,
|
|
}
|
|
}
|
|
|
|
return domain.User{
|
|
ID: 111,
|
|
Name: "name",
|
|
CreatedAt: now,
|
|
}, nil
|
|
})
|
|
},
|
|
apiKey: uuid.NewString(),
|
|
serverKey: "pl151",
|
|
expectedStatus: http.StatusUnauthorized,
|
|
target: &model.ErrorResp{},
|
|
expectedResponse: &model.ErrorResp{
|
|
Error: model.APIError{
|
|
Code: "unauthorized",
|
|
Message: "invalid API key",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
apiKeySvc := &mock.FakeAPIKeyVerifier{}
|
|
sessionSvc := &mock.FakeSessionService{}
|
|
tt.setup(apiKeySvc, sessionSvc)
|
|
|
|
router := newRouter(withAPIKeyVerifier(apiKeySvc), withSessionService(sessionSvc))
|
|
|
|
resp := doRequest(router, http.MethodGet, "/v1/user/sessions/"+tt.serverKey, tt.apiKey, nil)
|
|
defer resp.Body.Close()
|
|
assertJSONResponse(t, resp, tt.expectedStatus, tt.expectedResponse, tt.target)
|
|
})
|
|
}
|
|
}
|