package service import ( "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" "net/http" "testing" "git.urec56.ru/urec/chat_back_go/config" "git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/logger" mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks" ) func Test_newAuthService(t *testing.T) { c := gomock.NewController(t) defer c.Finish() cfg := config.JWT{} log := logger.NewLogger(config.Config{Mode: "TEST"}) serv := newAuthService(cfg, log) assert.Equal(t, &authService{cfg: cfg, parser: jwt.NewParser(), l: log}, serv) } func TestAuthService_keyFunc(t *testing.T) { testTable := []struct { name string token *jwt.Token cfgSecretKey []byte expectedKey any expectedErr error }{ { name: "ok_1", cfgSecretKey: []byte("secretKey"), expectedKey: []byte("secretKey"), }, { name: "ok_2", cfgSecretKey: []byte("another_secretKey"), expectedKey: []byte("another_secretKey"), }, } for _, tc := range testTable { t.Run(tc.name, func(t *testing.T) { serv := &authService{cfg: config.JWT{SecretKey: tc.cfgSecretKey}} key, err := serv.keyFunc(tc.token) assert.Equal(t, tc.expectedKey, key) assert.Equal(t, tc.expectedErr, err) }) } } func TestAuthService_ExtractAuthToken(t *testing.T) { testTable := []struct { name string req *http.Request reqHeader string reqToken string isError bool expectedToken string }{ { name: "ok_1", req: &http.Request{Header: http.Header{}}, reqHeader: "Authorization", reqToken: "Bearer 123", expectedToken: "123", }, { name: "ok_2", req: &http.Request{Header: http.Header{}}, reqHeader: "authorization", reqToken: "bearer 123", expectedToken: "123", }, { name: "incorrect_header", req: &http.Request{Header: http.Header{}}, reqToken: "Bearer 123", isError: true, }, { name: "incorrect_token_prefix", req: &http.Request{Header: http.Header{}}, reqHeader: "authorization", reqToken: "Beaer 123", isError: true, }, { name: "incorrect_token", req: &http.Request{Header: http.Header{}}, reqHeader: "authorization", reqToken: "Bearer", isError: true, }, { name: "incorrect_token_length", req: &http.Request{Header: http.Header{}}, reqHeader: "authorization", reqToken: "123", isError: true, }, } for _, tc := range testTable { t.Run(tc.name, func(t *testing.T) { tc.req.Header.Set(tc.reqHeader, tc.reqToken) auth := newAuthService(config.JWT{}, &logger.Logger{}) token, err := auth.ExtractAuthToken(tc.req) assert.Equal(t, tc.expectedToken, token) assert.Equal(t, tc.isError, err != nil) }) } } func TestAuthService_DecodeAuthToken(t *testing.T) { type parserBehavior func(p *mock_service.MockParser, token string, keyFunc jwt.Keyfunc, jwtToken *jwt.Token, err error) type jwtTokenConstructor func(claims Claims) *jwt.Token type claimsBehavior func(c *mock_service.MockClaims, subject string, err error) testTable := []struct { name string parserBehavior parserBehavior claimsBehavior claimsBehavior jwtTokenConstructor jwtTokenConstructor parserToken string parserErr error claimsUserID string claimsErr error secretKey []byte keyFuncErr error expectedUserID int expectedErr error }{ { name: "ok", parserBehavior: func(p *mock_service.MockParser, token string, keyFunc jwt.Keyfunc, jwtToken *jwt.Token, err error) { p.EXPECT().Parse(token, gomock.Any()).Return(jwtToken, err) }, claimsBehavior: func(c *mock_service.MockClaims, subject string, err error) { c.EXPECT().GetSubject().Return(subject, err) }, jwtTokenConstructor: func(claims Claims) *jwt.Token { return &jwt.Token{Claims: claims} }, parserToken: "token", claimsUserID: "1", secretKey: []byte("secret_key"), expectedUserID: 1, }, { name: "parser_error", parserBehavior: func(p *mock_service.MockParser, token string, keyFunc jwt.Keyfunc, jwtToken *jwt.Token, err error) { p.EXPECT().Parse(token, gomock.Any()).Return(jwtToken, err) }, claimsBehavior: func(c *mock_service.MockClaims, subject string, err error) {}, jwtTokenConstructor: func(claims Claims) *jwt.Token { return &jwt.Token{} }, parserToken: "token", parserErr: domain.AnyError, expectedErr: domain.TokenError, }, { name: "claims_error", parserBehavior: func(p *mock_service.MockParser, token string, keyFunc jwt.Keyfunc, jwtToken *jwt.Token, err error) { p.EXPECT().Parse(token, gomock.Any()).Return(jwtToken, err) }, claimsBehavior: func(c *mock_service.MockClaims, subject string, err error) { c.EXPECT().GetSubject().Return(subject, err) }, jwtTokenConstructor: func(claims Claims) *jwt.Token { return &jwt.Token{Claims: claims} }, parserToken: "token", secretKey: []byte("secret_key"), claimsErr: domain.AnyError, expectedErr: domain.TokenError, }, { name: "incorrect_id", parserBehavior: func(p *mock_service.MockParser, token string, keyFunc jwt.Keyfunc, jwtToken *jwt.Token, err error) { p.EXPECT().Parse(token, gomock.Any()).Return(jwtToken, err) }, claimsBehavior: func(c *mock_service.MockClaims, subject string, err error) { c.EXPECT().GetSubject().Return(subject, err) }, jwtTokenConstructor: func(claims Claims) *jwt.Token { return &jwt.Token{Claims: claims} }, parserToken: "token", claimsUserID: "not_number", secretKey: []byte("secret_key"), expectedErr: domain.TokenError, }, } for _, tc := range testTable { t.Run(tc.name, func(t *testing.T) { c := gomock.NewController(t) defer c.Finish() parser := mock_service.NewMockParser(c) claims := mock_service.NewMockClaims(c) jwtToken := tc.jwtTokenConstructor(claims) tc.claimsBehavior(claims, tc.claimsUserID, tc.claimsErr) serv := &authService{cfg: config.JWT{SecretKey: tc.secretKey}, parser: parser} tc.parserBehavior(parser, tc.parserToken, serv.keyFunc, jwtToken, tc.parserErr) userID, err := serv.DecodeAuthToken(tc.parserToken) assert.Equal(t, tc.expectedUserID, userID) assert.Equal(t, tc.expectedErr, err) }) } }