mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-04 13:21:45 +00:00
ci/cd: add basic static analysis for backend (#389)
This commit is contained in:
36
.github/workflows/backend-linter.yml
vendored
Normal file
36
.github/workflows/backend-linter.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: Run Backend Linter
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
permissions:
|
||||||
|
# Required: allow read access to the content for analysis.
|
||||||
|
contents: read
|
||||||
|
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
||||||
|
pull-requests: read
|
||||||
|
# Optional: allow write access to checks to allow the action to annotate code in the PR.
|
||||||
|
checks: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
golangci-lint:
|
||||||
|
name: Run Golangci-lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: backend/go.mod
|
||||||
|
|
||||||
|
- name: Run Golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2
|
||||||
|
with:
|
||||||
|
version: v1.64
|
||||||
|
working-directory: backend
|
||||||
|
only-new-issues: ${{ github.event_name == 'pull_request' }}
|
||||||
21
backend/.golangci.yml
Normal file
21
backend/.golangci.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
linters:
|
||||||
|
# Disable all linters.
|
||||||
|
# Default: false
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- gosec
|
||||||
|
- gocognit
|
||||||
|
|
||||||
|
presets:
|
||||||
|
- bugs
|
||||||
|
- sql
|
||||||
|
run:
|
||||||
|
timeout: "5m"
|
||||||
|
tests: true
|
||||||
@@ -56,17 +56,17 @@ func migrateDatabase(driver database.Driver) error {
|
|||||||
// Use the embedded migrations
|
// Use the embedded migrations
|
||||||
source, err := iofs.New(resources.FS, "migrations/"+string(common.EnvConfig.DbProvider))
|
source, err := iofs.New(resources.FS, "migrations/"+string(common.EnvConfig.DbProvider))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create embedded migration source: %v", err)
|
return fmt.Errorf("failed to create embedded migration source: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := migrate.NewWithInstance("iofs", source, "pocket-id", driver)
|
m, err := migrate.NewWithInstance("iofs", source, "pocket-id", driver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create migration instance: %v", err)
|
return fmt.Errorf("failed to create migration instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.Up()
|
err = m.Up()
|
||||||
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||||
return fmt.Errorf("failed to apply migrations: %v", err)
|
return fmt.Errorf("failed to apply migrations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func (s *GeoLiteService) updateDatabase() error {
|
|||||||
log.Println("Updating GeoLite2 City database...")
|
log.Println("Updating GeoLite2 City database...")
|
||||||
downloadUrl := fmt.Sprintf(common.EnvConfig.GeoLiteDBUrl, common.EnvConfig.MaxMindLicenseKey)
|
downloadUrl := fmt.Sprintf(common.EnvConfig.GeoLiteDBUrl, common.EnvConfig.MaxMindLicenseKey)
|
||||||
|
|
||||||
// Download the database tar.gz file
|
// Download the database tar.gz file nolint:gosec
|
||||||
resp, err := http.Get(downloadUrl)
|
resp, err := http.Get(downloadUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to download database: %w", err)
|
return fmt.Errorf("failed to download database: %w", err)
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ func (s *LdapService) SyncGroups() error {
|
|||||||
// Get all LDAP groups from the database
|
// Get all LDAP groups from the database
|
||||||
var ldapGroupsInDb []model.UserGroup
|
var ldapGroupsInDb []model.UserGroup
|
||||||
if err := s.db.Find(&ldapGroupsInDb, "ldap_id IS NOT NULL").Select("ldap_id").Error; err != nil {
|
if err := s.db.Find(&ldapGroupsInDb, "ldap_id IS NOT NULL").Select("ldap_id").Error; err != nil {
|
||||||
fmt.Println(fmt.Errorf("failed to fetch groups from database: %v", err))
|
fmt.Println(fmt.Errorf("failed to fetch groups from database: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete groups that no longer exist in LDAP
|
// Delete groups that no longer exist in LDAP
|
||||||
@@ -276,7 +276,7 @@ func (s *LdapService) SyncUsers() error {
|
|||||||
// Get all LDAP users from the database
|
// Get all LDAP users from the database
|
||||||
var ldapUsersInDb []model.User
|
var ldapUsersInDb []model.User
|
||||||
if err := s.db.Find(&ldapUsersInDb, "ldap_id IS NOT NULL").Select("ldap_id").Error; err != nil {
|
if err := s.db.Find(&ldapUsersInDb, "ldap_id IS NOT NULL").Select("ldap_id").Error; err != nil {
|
||||||
fmt.Println(fmt.Errorf("failed to fetch users from database: %v", err))
|
fmt.Println(fmt.Errorf("failed to fetch users from database: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete users that no longer exist in LDAP
|
// Delete users that no longer exist in LDAP
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ func (s *OidcService) GetUserClaimsForClient(userID string, clientID string) (ma
|
|||||||
for _, customClaim := range customClaims {
|
for _, customClaim := range customClaims {
|
||||||
// The value of the custom claim can be a JSON object or a string
|
// The value of the custom claim can be a JSON object or a string
|
||||||
var jsonValue interface{}
|
var jsonValue interface{}
|
||||||
|
//nolint:errcheck // Ignore error for JSON unmarshalling
|
||||||
json.Unmarshal([]byte(customClaim.Value), &jsonValue)
|
json.Unmarshal([]byte(customClaim.Value), &jsonValue)
|
||||||
if jsonValue != nil {
|
if jsonValue != nil {
|
||||||
// It's JSON so we store it as an object
|
// It's JSON so we store it as an object
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ func (s *UserService) CreateOneTimeAccessToken(userID string, expiresAt time.Tim
|
|||||||
tokenLength := 16
|
tokenLength := 16
|
||||||
|
|
||||||
// If expires at is less than 15 minutes, use an 6 character token instead of 16
|
// If expires at is less than 15 minutes, use an 6 character token instead of 16
|
||||||
if expiresAt.Sub(time.Now()) <= 15*time.Minute {
|
if time.Until(expiresAt) <= 15*time.Minute {
|
||||||
tokenLength = 6
|
tokenLength = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ func (c *Composer) String() string {
|
|||||||
|
|
||||||
func convertRunes(str string) []string {
|
func convertRunes(str string) []string {
|
||||||
var enc = make([]string, 0, len(str))
|
var enc = make([]string, 0, len(str))
|
||||||
for _, r := range []rune(str) {
|
for _, r := range str {
|
||||||
if r == ' ' {
|
if r == ' ' {
|
||||||
enc = append(enc, "_")
|
enc = append(enc, "_")
|
||||||
} else if isPrintableASCIIRune(r) &&
|
} else if isPrintableASCIIRune(r) &&
|
||||||
@@ -204,7 +204,7 @@ func hex(n byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isPrintableASCII(str string) bool {
|
func isPrintableASCII(str string) bool {
|
||||||
for _, r := range []rune(str) {
|
for _, r := range str {
|
||||||
if !unicode.IsPrint(r) || r >= unicode.MaxASCII {
|
if !unicode.IsPrint(r) || r >= unicode.MaxASCII {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user