mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-12 08:13:01 +03:00
ci/cd: migrate backend linter to v2. fixed unit test workflow (#400)
This commit is contained in:
4
.github/workflows/backend-linter.yml
vendored
4
.github/workflows/backend-linter.yml
vendored
@@ -32,8 +32,8 @@ jobs:
|
||||
go-version-file: backend/go.mod
|
||||
|
||||
- name: Run Golangci-lint
|
||||
uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2
|
||||
uses: golangci/golangci-lint-action@dec74fa03096ff515422f71d18d41307cacde373 # v7.0.0
|
||||
with:
|
||||
version: v1.64
|
||||
version: v2.0.2
|
||||
working-directory: backend
|
||||
only-new-issues: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
1
.github/workflows/unit-tests.yml
vendored
1
.github/workflows/unit-tests.yml
vendored
@@ -25,6 +25,7 @@ jobs:
|
||||
- name: Run backend unit tests
|
||||
working-directory: backend
|
||||
run: |
|
||||
set -e -o pipefail
|
||||
go test -v ./... | tee /tmp/TestResults.log
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
|
||||
@@ -1,25 +1,64 @@
|
||||
|
||||
version: "2"
|
||||
run:
|
||||
tests: true
|
||||
timeout: 5m
|
||||
linters:
|
||||
# Disable all linters.
|
||||
# Default: false
|
||||
disable-all: true
|
||||
default: none
|
||||
enable:
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- bidichk
|
||||
- bodyclose
|
||||
- contextcheck
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- gosimple
|
||||
- errchkjson
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- gocheckcompilerdirectives
|
||||
- gochecksumtype
|
||||
- gocognit
|
||||
- gocritic
|
||||
- gosec
|
||||
- gosmopolitan
|
||||
- govet
|
||||
- ineffassign
|
||||
- loggercheck
|
||||
- makezero
|
||||
- musttag
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- noctx
|
||||
- protogetter
|
||||
- reassign
|
||||
- recvcheck
|
||||
- rowserrcheck
|
||||
- spancheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- testifylint
|
||||
- unused
|
||||
- gosec
|
||||
- gocognit
|
||||
|
||||
presets:
|
||||
- bugs
|
||||
- sql
|
||||
- usestdlibvars
|
||||
- zerologlint
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- internal/service/test_service.go
|
||||
|
||||
run:
|
||||
timeout: "5m"
|
||||
tests: true
|
||||
formatters:
|
||||
enable:
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/pocket-id/pocket-id/backend
|
||||
|
||||
go 1.23.1
|
||||
go 1.23.7
|
||||
|
||||
require (
|
||||
github.com/caarlos0/env/v11 v11.3.1
|
||||
|
||||
@@ -240,12 +240,13 @@ func (oc *OidcController) EndSessionHandler(c *gin.Context) {
|
||||
var input dto.OidcLogoutDto
|
||||
|
||||
// Bind query parameters to the struct
|
||||
if c.Request.Method == http.MethodGet {
|
||||
switch c.Request.Method {
|
||||
case http.MethodGet:
|
||||
if err := c.ShouldBindQuery(&input); err != nil {
|
||||
_ = c.Error(err)
|
||||
return
|
||||
}
|
||||
} else if c.Request.Method == http.MethodPost {
|
||||
case http.MethodPost:
|
||||
// Bind form parameters to the struct
|
||||
if err := c.ShouldBind(&input); err != nil {
|
||||
_ = c.Error(err)
|
||||
|
||||
@@ -63,13 +63,14 @@ func mapStructInternal(sourceVal reflect.Value, destVal reflect.Value) error {
|
||||
}
|
||||
|
||||
func mapField(sourceField reflect.Value, destField reflect.Value) error {
|
||||
if sourceField.Type() == destField.Type() {
|
||||
switch {
|
||||
case sourceField.Type() == destField.Type():
|
||||
destField.Set(sourceField)
|
||||
} else if sourceField.Kind() == reflect.Slice && destField.Kind() == reflect.Slice {
|
||||
case sourceField.Kind() == reflect.Slice && destField.Kind() == reflect.Slice:
|
||||
return mapSlice(sourceField, destField)
|
||||
} else if sourceField.Kind() == reflect.Struct && destField.Kind() == reflect.Struct {
|
||||
case sourceField.Kind() == reflect.Struct && destField.Kind() == reflect.Struct:
|
||||
return mapStructInternal(sourceField, destField)
|
||||
} else {
|
||||
default:
|
||||
return mapSpecialTypes(sourceField, destField)
|
||||
}
|
||||
return nil
|
||||
@@ -98,8 +99,7 @@ func mapSlice(sourceField reflect.Value, destField reflect.Value) error {
|
||||
}
|
||||
|
||||
func mapSpecialTypes(sourceField reflect.Value, destField reflect.Value) error {
|
||||
switch sourceField.Interface().(type) {
|
||||
case datatype.DateTime:
|
||||
if _, ok := sourceField.Interface().(datatype.DateTime); ok {
|
||||
if sourceField.Type() == reflect.TypeOf(datatype.DateTime{}) && destField.Type() == reflect.TypeOf(time.Time{}) {
|
||||
dateValue := sourceField.Interface().(datatype.DateTime)
|
||||
destField.Set(reflect.ValueOf(dateValue.ToTime()))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"log"
|
||||
"regexp"
|
||||
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
var validateUsername validator.Func = func(fl validator.FieldLevel) bool {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/common"
|
||||
)
|
||||
@@ -23,7 +25,7 @@ func (m *CorsMiddleware) Add() gin.HandlerFunc {
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "*")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
|
||||
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
if c.Request.Method == http.MethodOptions {
|
||||
c.AbortWithStatus(204)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
)
|
||||
import datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
|
||||
type ApiKey struct {
|
||||
Base
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@ package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
datatype "github.com/pocket-id/pocket-id/backend/internal/model/types"
|
||||
|
||||
"github.com/pocket-id/pocket-id/backend/internal/common"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/dto"
|
||||
"github.com/pocket-id/pocket-id/backend/internal/model"
|
||||
|
||||
@@ -105,9 +105,10 @@ func (s *CustomClaimService) updateCustomClaims(idType idType, value string, cla
|
||||
Value: claim.Value,
|
||||
}
|
||||
|
||||
if idType == UserID {
|
||||
switch idType {
|
||||
case UserID:
|
||||
customClaim.UserID = &value
|
||||
} else if idType == UserGroupID {
|
||||
case UserGroupID:
|
||||
customClaim.UserGroupID = &value
|
||||
}
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ func TestGenerateVerifyAccessToken(t *testing.T) {
|
||||
assert.False(t, isAdmin, "isAdmin should be false")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{"https://test.example.com"}, audience, "Audience should contain the app URL")
|
||||
assert.Equal(t, []string{"https://test.example.com"}, audience, "Audience should contain the app URL")
|
||||
|
||||
// Check token expiration time is approximately 1 hour from now
|
||||
expectedExp := time.Now().Add(1 * time.Hour)
|
||||
@@ -606,7 +606,7 @@ func TestGenerateVerifyIdToken(t *testing.T) {
|
||||
assert.Equal(t, "user123", subject, "Token subject should match user ID")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
assert.Equal(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
issuer, ok := claims.Issuer()
|
||||
_ = assert.True(t, ok, "Issuer not found in token") &&
|
||||
assert.Equal(t, common.EnvConfig.AppURL, issuer, "Issuer should match app URL")
|
||||
@@ -935,7 +935,7 @@ func TestGenerateVerifyOauthAccessToken(t *testing.T) {
|
||||
assert.Equal(t, user.ID, subject, "Token subject should match user ID")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
assert.Equal(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
issuer, ok := claims.Issuer()
|
||||
_ = assert.True(t, ok, "Issuer not found in token") &&
|
||||
assert.Equal(t, common.EnvConfig.AppURL, issuer, "Issuer should match app URL")
|
||||
@@ -1050,7 +1050,7 @@ func TestGenerateVerifyOauthAccessToken(t *testing.T) {
|
||||
assert.Equal(t, user.ID, subject, "Token subject should match user ID")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
assert.Equal(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
|
||||
// Verify the key type is OKP
|
||||
publicKey, err := service.GetPublicJWK()
|
||||
@@ -1104,7 +1104,7 @@ func TestGenerateVerifyOauthAccessToken(t *testing.T) {
|
||||
assert.Equal(t, user.ID, subject, "Token subject should match user ID")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
assert.Equal(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
|
||||
// Verify the key type is EC
|
||||
publicKey, err := service.GetPublicJWK()
|
||||
@@ -1158,7 +1158,7 @@ func TestGenerateVerifyOauthAccessToken(t *testing.T) {
|
||||
assert.Equal(t, user.ID, subject, "Token subject should match user ID")
|
||||
audience, ok := claims.Audience()
|
||||
_ = assert.True(t, ok, "Audience not found in token") &&
|
||||
assert.EqualValues(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
assert.Equal(t, []string{clientID}, audience, "Audience should contain the client ID")
|
||||
|
||||
// Verify the key type is RSA
|
||||
publicKey, err := service.GetPublicJWK()
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestGetAuthenticatorName(t *testing.T) {
|
||||
|
||||
// Inject a test AAGUID map
|
||||
aaguidMap = map[string]string{
|
||||
"adce0002-35bc-c60a-648b-m0b25f1f05503": "Test Authenticator",
|
||||
"adce0002-35bc-c60a-648b-0b25f1f05503": "Test Authenticator",
|
||||
"00000000-0000-0000-0000-000000000000": "Zero Authenticator",
|
||||
}
|
||||
aaguidMapOnce = sync.Once{}
|
||||
|
||||
@@ -171,14 +171,12 @@ func (c *Composer) String() string {
|
||||
func convertRunes(str string) []string {
|
||||
var enc = make([]string, 0, len(str))
|
||||
for _, r := range str {
|
||||
if r == ' ' {
|
||||
switch {
|
||||
case r == ' ':
|
||||
enc = append(enc, "_")
|
||||
} else if isPrintableASCIIRune(r) &&
|
||||
r != '=' &&
|
||||
r != '?' &&
|
||||
r != '_' {
|
||||
case isPrintableASCIIRune(r) && r != '=' && r != '?' && r != '_':
|
||||
enc = append(enc, string(r))
|
||||
} else {
|
||||
default:
|
||||
enc = append(enc, string(toHex([]byte(string(r)))))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user