Linting fixes

This commit is contained in:
Hein 2025-11-11 11:03:02 +02:00
parent 412bbab560
commit 682716dd31
21 changed files with 302 additions and 290 deletions

129
.golangci.json Normal file
View File

@ -0,0 +1,129 @@
{
"formatters": {
"enable": [
"gofmt",
"goimports"
],
"exclusions": {
"generated": "lax",
"paths": [
"third_party$",
"builtin$",
"examples$"
]
},
"settings": {
"gofmt": {
"simplify": true
},
"goimports": {
"local-prefixes": [
"github.com/bitechdev/ResolveSpec"
]
}
}
},
"issues": {
"max-issues-per-linter": 0,
"max-same-issues": 0
},
"linters": {
"enable": [
"gocritic",
"misspell",
"revive"
],
"exclusions": {
"generated": "lax",
"paths": [
"third_party$",
"builtin$",
"examples$",
"mocks?",
"tests?"
],
"rules": [
{
"linters": [
"dupl",
"errcheck",
"gocritic",
"gosec"
],
"path": "_test\\.go"
},
{
"linters": [
"errcheck"
],
"text": "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked"
},
{
"path": "_test\\.go",
"text": "cognitive complexity|cyclomatic complexity"
}
]
},
"settings": {
"errcheck": {
"check-blank": false,
"check-type-assertions": false
},
"gocritic": {
"enabled-checks": [
"appendAssign",
"assignOp",
"boolExprSimplify",
"builtinShadow",
"captLocal",
"caseOrder",
"defaultCaseOrder",
"dupArg",
"dupBranchBody",
"dupCase",
"dupSubExpr",
"elseif",
"emptyFallthrough",
"equalFold",
"flagName",
"ifElseChain",
"indexAlloc",
"initClause",
"methodExprCall",
"nilValReturn",
"rangeExprCopy",
"rangeValCopy",
"regexpMust",
"singleCaseSwitch",
"sloppyLen",
"stringXbytes",
"switchTrue",
"typeAssertChain",
"typeSwitchVar",
"underef",
"unlabelStmt",
"unnamedResult",
"unnecessaryBlock",
"weakCond",
"yodaStyleExpr"
]
},
"revive": {
"rules": [
{
"disabled": true,
"name": "exported"
},
{
"disabled": true,
"name": "package-comments"
}
]
}
}
},
"run": {
"tests": true
},
"version": "2"
}

View File

@ -1,110 +0,0 @@
run:
timeout: 5m
tests: true
skip-dirs:
- vendor
- .github
linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- gofmt
- goimports
- misspell
- gocritic
- revive
- stylecheck
disable:
- typecheck # Can cause issues with generics in some cases
linters-settings:
errcheck:
check-type-assertions: false
check-blank: false
govet:
check-shadowing: false
gofmt:
simplify: true
goimports:
local-prefixes: github.com/bitechdev/ResolveSpec
gocritic:
enabled-checks:
- appendAssign
- assignOp
- boolExprSimplify
- builtinShadow
- captLocal
- caseOrder
- defaultCaseOrder
- dupArg
- dupBranchBody
- dupCase
- dupSubExpr
- elseif
- emptyFallthrough
- equalFold
- flagName
- ifElseChain
- indexAlloc
- initClause
- methodExprCall
- nilValReturn
- rangeExprCopy
- rangeValCopy
- regexpMust
- singleCaseSwitch
- sloppyLen
- stringXbytes
- switchTrue
- typeAssertChain
- typeSwitchVar
- underef
- unlabelStmt
- unnamedResult
- unnecessaryBlock
- weakCond
- yodaStyleExpr
revive:
rules:
- name: exported
disabled: true
- name: package-comments
disabled: true
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0
# Exclude some linters from running on tests files
exclude-rules:
- path: _test\.go
linters:
- errcheck
- dupl
- gosec
- gocritic
# Ignore "error return value not checked" for defer statements
- linters:
- errcheck
text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked"
# Ignore complexity in test files
- path: _test\.go
text: "cognitive complexity|cyclomatic complexity"
output:
format: colored-line-number
print-issued-lines: true
print-linter-name: true

View File

@ -6,8 +6,9 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/bitechdev/ResolveSpec/pkg/common"
"github.com/uptrace/bun" "github.com/uptrace/bun"
"github.com/bitechdev/ResolveSpec/pkg/common"
) )
// BunAdapter adapts Bun to work with our Database interface // BunAdapter adapts Bun to work with our Database interface

View File

@ -5,8 +5,9 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/bitechdev/ResolveSpec/pkg/common"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/bitechdev/ResolveSpec/pkg/common"
) )
// GormAdapter adapts GORM to work with our Database interface // GormAdapter adapts GORM to work with our Database interface

View File

@ -3,8 +3,9 @@ package router
import ( import (
"net/http" "net/http"
"github.com/bitechdev/ResolveSpec/pkg/common"
"github.com/uptrace/bunrouter" "github.com/uptrace/bunrouter"
"github.com/bitechdev/ResolveSpec/pkg/common"
) )
// BunRouterAdapter adapts uptrace/bunrouter to work with our Router interface // BunRouterAdapter adapts uptrace/bunrouter to work with our Router interface

View File

@ -5,8 +5,9 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/bitechdev/ResolveSpec/pkg/common"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/bitechdev/ResolveSpec/pkg/common"
) )
// MuxAdapter adapts Gorilla Mux to work with our Router interface // MuxAdapter adapts Gorilla Mux to work with our Router interface

View File

@ -210,7 +210,7 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
// Apply sorting // Apply sorting
for _, sort := range options.Sort { for _, sort := range options.Sort {
direction := "ASC" direction := "ASC"
if strings.ToLower(sort.Direction) == "desc" { if strings.EqualFold(sort.Direction, "desc") {
direction = "DESC" direction = "DESC"
} }
logger.Debug("Applying sort: %s %s", sort.Column, direction) logger.Debug("Applying sort: %s %s", sort.Column, direction)
@ -969,17 +969,20 @@ func (h *Handler) generateMetadata(schema, entity string, model interface{}) *co
func (h *Handler) sendResponse(w common.ResponseWriter, data interface{}, metadata *common.Metadata) { func (h *Handler) sendResponse(w common.ResponseWriter, data interface{}, metadata *common.Metadata) {
w.SetHeader("Content-Type", "application/json") w.SetHeader("Content-Type", "application/json")
w.WriteJSON(common.Response{ err := w.WriteJSON(common.Response{
Success: true, Success: true,
Data: data, Data: data,
Metadata: metadata, Metadata: metadata,
}) })
if err != nil {
logger.Error("Error sending response: %v", err)
}
} }
func (h *Handler) sendError(w common.ResponseWriter, status int, code, message string, details interface{}) { func (h *Handler) sendError(w common.ResponseWriter, status int, code, message string, details interface{}) {
w.SetHeader("Content-Type", "application/json") w.SetHeader("Content-Type", "application/json")
w.WriteHeader(status) w.WriteHeader(status)
w.WriteJSON(common.Response{ err := w.WriteJSON(common.Response{
Success: false, Success: false,
Error: &common.APIError{ Error: &common.APIError{
Code: code, Code: code,
@ -988,6 +991,9 @@ func (h *Handler) sendError(w common.ResponseWriter, status int, code, message s
Detail: fmt.Sprintf("%v", details), Detail: fmt.Sprintf("%v", details),
}, },
}) })
if err != nil {
logger.Error("Error sending response: %v", err)
}
} }
// RegisterModel allows registering models at runtime // RegisterModel allows registering models at runtime

View File

@ -3,13 +3,14 @@ package resolvespec
import ( import (
"net/http" "net/http"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/database"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/router"
"github.com/bitechdev/ResolveSpec/pkg/modelregistry"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/uptrace/bun" "github.com/uptrace/bun"
"github.com/uptrace/bunrouter" "github.com/uptrace/bunrouter"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/database"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/router"
"github.com/bitechdev/ResolveSpec/pkg/modelregistry"
) )
// NewHandlerWithGORM creates a new Handler with GORM adapter // NewHandlerWithGORM creates a new Handler with GORM adapter

View File

@ -140,19 +140,19 @@ func (opts *ExtendedRequestOptions) GetCursorFilter(
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
// Helper: get active cursor (forward or backward) // Helper: get active cursor (forward or backward)
func (opts *ExtendedRequestOptions) getActiveCursor() (id string, direction CursorDirection) { func (opts *ExtendedRequestOptions) getActiveCursor() (id string, direction CursorDirection) {
if opts.RequestOptions.CursorForward != "" { if opts.CursorForward != "" {
return opts.RequestOptions.CursorForward, CursorForward return opts.CursorForward, CursorForward
} }
if opts.RequestOptions.CursorBackward != "" { if opts.CursorBackward != "" {
return opts.RequestOptions.CursorBackward, CursorBackward return opts.CursorBackward, CursorBackward
} }
return "", 0 return "", 0
} }
// Helper: extract sort columns // Helper: extract sort columns
func (opts *ExtendedRequestOptions) getSortColumns() []common.SortOption { func (opts *ExtendedRequestOptions) getSortColumns() []common.SortOption {
if opts.RequestOptions.Sort != nil { if opts.Sort != nil {
return opts.RequestOptions.Sort return opts.Sort
} }
return nil return nil
} }

View File

@ -318,7 +318,7 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
// Apply sorting // Apply sorting
for _, sort := range options.Sort { for _, sort := range options.Sort {
direction := "ASC" direction := "ASC"
if strings.ToLower(sort.Direction) == "desc" { if strings.EqualFold(sort.Direction, "desc") {
direction = "DESC" direction = "DESC"
} }
logger.Debug("Applying sort: %s %s", sort.Column, direction) logger.Debug("Applying sort: %s %s", sort.Column, direction)
@ -352,7 +352,7 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
} }
// Apply cursor-based pagination // Apply cursor-based pagination
if len(options.RequestOptions.CursorForward) > 0 || len(options.RequestOptions.CursorBackward) > 0 { if len(options.CursorForward) > 0 || len(options.CursorBackward) > 0 {
logger.Debug("Applying cursor pagination") logger.Debug("Applying cursor pagination")
// Get primary key name // Get primary key name
@ -425,9 +425,9 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
} }
// Fetch row number for a specific record if requested // Fetch row number for a specific record if requested
if options.RequestOptions.FetchRowNumber != nil && *options.RequestOptions.FetchRowNumber != "" { if options.FetchRowNumber != nil && *options.FetchRowNumber != "" {
pkName := reflection.GetPrimaryKeyName(model) pkName := reflection.GetPrimaryKeyName(model)
pkValue := *options.RequestOptions.FetchRowNumber pkValue := *options.FetchRowNumber
logger.Debug("Fetching row number for specific PK %s = %s", pkName, pkValue) logger.Debug("Fetching row number for specific PK %s = %s", pkName, pkValue)
@ -1415,7 +1415,7 @@ func (h *Handler) FetchRowNumber(ctx context.Context, tableName string, pkName s
sortParts := make([]string, 0, len(options.Sort)) sortParts := make([]string, 0, len(options.Sort))
for _, sort := range options.Sort { for _, sort := range options.Sort {
direction := "ASC" direction := "ASC"
if strings.ToLower(sort.Direction) == "desc" { if strings.EqualFold(sort.Direction, "desc") {
direction = "DESC" direction = "DESC"
} }
sortParts = append(sortParts, fmt.Sprintf("%s.%s %s", tableName, sort.Column, direction)) sortParts = append(sortParts, fmt.Sprintf("%s.%s %s", tableName, sort.Column, direction))

View File

@ -2,7 +2,6 @@ package restheadspec
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"strconv" "strconv"
@ -59,7 +58,7 @@ func decodeHeaderValue(value string) string {
// DecodeParam - Decodes parameter string and returns unencoded string // DecodeParam - Decodes parameter string and returns unencoded string
func DecodeParam(pStr string) (string, error) { func DecodeParam(pStr string) (string, error) {
var code string = pStr var code = pStr
if strings.HasPrefix(pStr, "ZIP_") { if strings.HasPrefix(pStr, "ZIP_") {
code = strings.ReplaceAll(pStr, "ZIP_", "") code = strings.ReplaceAll(pStr, "ZIP_", "")
code = strings.ReplaceAll(code, "\n", "") code = strings.ReplaceAll(code, "\n", "")
@ -125,7 +124,7 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
case strings.HasPrefix(normalizedKey, "x-not-select-fields"): case strings.HasPrefix(normalizedKey, "x-not-select-fields"):
h.parseNotSelectFields(&options, decodedValue) h.parseNotSelectFields(&options, decodedValue)
case strings.HasPrefix(normalizedKey, "x-clean-json"): case strings.HasPrefix(normalizedKey, "x-clean-json"):
options.CleanJSON = strings.ToLower(decodedValue) == "true" options.CleanJSON = strings.EqualFold(decodedValue, "true")
// Filtering & Search // Filtering & Search
case strings.HasPrefix(normalizedKey, "x-fieldfilter-"): case strings.HasPrefix(normalizedKey, "x-fieldfilter-"):
@ -166,9 +165,9 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
options.Offset = &offset options.Offset = &offset
} }
case strings.HasPrefix(normalizedKey, "x-cursor-forward"): case strings.HasPrefix(normalizedKey, "x-cursor-forward"):
options.RequestOptions.CursorForward = decodedValue options.CursorForward = decodedValue
case strings.HasPrefix(normalizedKey, "x-cursor-backward"): case strings.HasPrefix(normalizedKey, "x-cursor-backward"):
options.RequestOptions.CursorBackward = decodedValue options.CursorBackward = decodedValue
// Advanced Features // Advanced Features
case strings.HasPrefix(normalizedKey, "x-advsql-"): case strings.HasPrefix(normalizedKey, "x-advsql-"):
@ -178,13 +177,13 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
colName := strings.TrimPrefix(normalizedKey, "x-cql-sel-") colName := strings.TrimPrefix(normalizedKey, "x-cql-sel-")
options.ComputedQL[colName] = decodedValue options.ComputedQL[colName] = decodedValue
case strings.HasPrefix(normalizedKey, "x-distinct"): case strings.HasPrefix(normalizedKey, "x-distinct"):
options.Distinct = strings.ToLower(decodedValue) == "true" options.Distinct = strings.EqualFold(decodedValue, "true")
case strings.HasPrefix(normalizedKey, "x-skipcount"): case strings.HasPrefix(normalizedKey, "x-skipcount"):
options.SkipCount = strings.ToLower(decodedValue) == "true" options.SkipCount = strings.EqualFold(decodedValue, "true")
case strings.HasPrefix(normalizedKey, "x-skipcache"): case strings.HasPrefix(normalizedKey, "x-skipcache"):
options.SkipCache = strings.ToLower(decodedValue) == "true" options.SkipCache = strings.EqualFold(decodedValue, "true")
case strings.HasPrefix(normalizedKey, "x-fetch-rownumber"): case strings.HasPrefix(normalizedKey, "x-fetch-rownumber"):
options.RequestOptions.FetchRowNumber = &decodedValue options.FetchRowNumber = &decodedValue
case strings.HasPrefix(normalizedKey, "x-pkrow"): case strings.HasPrefix(normalizedKey, "x-pkrow"):
options.PKRow = &decodedValue options.PKRow = &decodedValue
@ -198,7 +197,7 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
// Transaction Control // Transaction Control
case strings.HasPrefix(normalizedKey, "x-transaction-atomic"): case strings.HasPrefix(normalizedKey, "x-transaction-atomic"):
options.AtomicTransaction = strings.ToLower(decodedValue) == "true" options.AtomicTransaction = strings.EqualFold(decodedValue, "true")
} }
} }
@ -455,16 +454,6 @@ func (h *Handler) parseCommaSeparated(value string) []string {
return result return result
} }
// parseJSONHeader parses a header value as JSON
func (h *Handler) parseJSONHeader(value string) (map[string]interface{}, error) {
var result map[string]interface{}
err := json.Unmarshal([]byte(value), &result)
if err != nil {
return nil, fmt.Errorf("failed to parse JSON header: %w", err)
}
return result, nil
}
// getColumnTypeFromModel uses reflection to determine the Go type of a column in a model // getColumnTypeFromModel uses reflection to determine the Go type of a column in a model
func (h *Handler) getColumnTypeFromModel(model interface{}, colName string) reflect.Kind { func (h *Handler) getColumnTypeFromModel(model interface{}, colName string) reflect.Kind {
if model == nil { if model == nil {
@ -536,11 +525,6 @@ func isStringType(kind reflect.Kind) bool {
return kind == reflect.String return kind == reflect.String
} }
// isBoolType checks if a reflect.Kind is a boolean type
func isBoolType(kind reflect.Kind) bool {
return kind == reflect.Bool
}
// convertToNumericType converts a string value to the appropriate numeric type // convertToNumericType converts a string value to the appropriate numeric type
func convertToNumericType(value string, kind reflect.Kind) (interface{}, error) { func convertToNumericType(value string, kind reflect.Kind) (interface{}, error) {
value = strings.TrimSpace(value) value = strings.TrimSpace(value)

View File

@ -55,13 +55,14 @@ package restheadspec
import ( import (
"net/http" "net/http"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/database"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/router"
"github.com/bitechdev/ResolveSpec/pkg/modelregistry"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/uptrace/bun" "github.com/uptrace/bun"
"github.com/uptrace/bunrouter" "github.com/uptrace/bunrouter"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/database"
"github.com/bitechdev/ResolveSpec/pkg/common/adapters/router"
"github.com/bitechdev/ResolveSpec/pkg/modelregistry"
) )
// NewHandlerWithGORM creates a new Handler with GORM adapter // NewHandlerWithGORM creates a new Handler with GORM adapter

View File

@ -1,14 +1,11 @@
package security package security
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
// DBM "github.com/bitechdev/GoCore/pkg/models"
DBM "github.com/bitechdev/GoCore/pkg/models"
"github.com/bitechdev/ResolveSpec/pkg/logger"
) )
// This file provides example implementations of the required security callbacks. // This file provides example implementations of the required security callbacks.
@ -121,104 +118,104 @@ func ExampleAuthenticateFromSession(r *http.Request) (userID int, roles string,
func ExampleLoadColumnSecurityFromDatabase(pUserID int, pSchema, pTablename string) ([]ColumnSecurity, error) { func ExampleLoadColumnSecurityFromDatabase(pUserID int, pSchema, pTablename string) ([]ColumnSecurity, error) {
colSecList := make([]ColumnSecurity, 0) colSecList := make([]ColumnSecurity, 0)
getExtraFilters := func(pStr string) map[string]string { // getExtraFilters := func(pStr string) map[string]string {
mp := make(map[string]string, 0) // mp := make(map[string]string, 0)
for i, val := range strings.Split(pStr, ",") { // for i, val := range strings.Split(pStr, ",") {
if i <= 1 { // if i <= 1 {
continue // continue
} // }
vals := strings.Split(val, ":") // vals := strings.Split(val, ":")
if len(vals) > 1 { // if len(vals) > 1 {
mp[vals[0]] = vals[1] // mp[vals[0]] = vals[1]
} // }
} // }
return mp // return mp
} // }
rows, err := DBM.DBConn.Raw(fmt.Sprintf(` // rows, err := DBM.DBConn.Raw(fmt.Sprintf(`
SELECT a.rid_secacces, a.control, a.accesstype, a.jsonvalue // SELECT a.rid_secacces, a.control, a.accesstype, a.jsonvalue
FROM core.secacces a // FROM core.secacces a
WHERE a.rid_hub IN ( // WHERE a.rid_hub IN (
SELECT l.rid_hub_parent // SELECT l.rid_hub_parent
FROM core.hub_link l // FROM core.hub_link l
WHERE l.parent_hubtype = 'secgroup' // WHERE l.parent_hubtype = 'secgroup'
AND l.rid_hub_child = ? // AND l.rid_hub_child = ?
) // )
AND control ILIKE '%s.%s%%' // AND control ILIKE '%s.%s%%'
`, pSchema, pTablename), pUserID).Rows() // `, pSchema, pTablename), pUserID).Rows()
defer func() { // defer func() {
if rows != nil { // if rows != nil {
rows.Close() // rows.Close()
} // }
}() // }()
if err != nil { // if err != nil {
return colSecList, fmt.Errorf("failed to fetch column security from SQL: %v", err) // return colSecList, fmt.Errorf("failed to fetch column security from SQL: %v", err)
} // }
for rows.Next() { // for rows.Next() {
var rid int // var rid int
var jsondata []byte // var jsondata []byte
var control, accesstype string // var control, accesstype string
err = rows.Scan(&rid, &control, &accesstype, &jsondata) // err = rows.Scan(&rid, &control, &accesstype, &jsondata)
if err != nil { // if err != nil {
return colSecList, fmt.Errorf("failed to scan column security: %v", err) // return colSecList, fmt.Errorf("failed to scan column security: %v", err)
} // }
parts := strings.Split(control, ",") // parts := strings.Split(control, ",")
ids := strings.Split(parts[0], ".") // ids := strings.Split(parts[0], ".")
if len(ids) < 3 { // if len(ids) < 3 {
continue // continue
} // }
jsonvalue := make(map[string]interface{}) // jsonvalue := make(map[string]interface{})
if len(jsondata) > 1 { // if len(jsondata) > 1 {
err = json.Unmarshal(jsondata, &jsonvalue) // err = json.Unmarshal(jsondata, &jsonvalue)
if err != nil { // if err != nil {
logger.Error("Failed to parse json: %v", err) // logger.Error("Failed to parse json: %v", err)
} // }
} // }
colsec := ColumnSecurity{ // colsec := ColumnSecurity{
Schema: pSchema, // Schema: pSchema,
Tablename: pTablename, // Tablename: pTablename,
UserID: pUserID, // UserID: pUserID,
Path: ids[2:], // Path: ids[2:],
ExtraFilters: getExtraFilters(control), // ExtraFilters: getExtraFilters(control),
Accesstype: accesstype, // Accesstype: accesstype,
Control: control, // Control: control,
ID: int(rid), // ID: int(rid),
} // }
// Parse masking configuration from JSON // // Parse masking configuration from JSON
if v, ok := jsonvalue["start"]; ok { // if v, ok := jsonvalue["start"]; ok {
if value, ok := v.(float64); ok { // if value, ok := v.(float64); ok {
colsec.MaskStart = int(value) // colsec.MaskStart = int(value)
} // }
} // }
if v, ok := jsonvalue["end"]; ok { // if v, ok := jsonvalue["end"]; ok {
if value, ok := v.(float64); ok { // if value, ok := v.(float64); ok {
colsec.MaskEnd = int(value) // colsec.MaskEnd = int(value)
} // }
} // }
if v, ok := jsonvalue["invert"]; ok { // if v, ok := jsonvalue["invert"]; ok {
if value, ok := v.(bool); ok { // if value, ok := v.(bool); ok {
colsec.MaskInvert = value // colsec.MaskInvert = value
} // }
} // }
if v, ok := jsonvalue["char"]; ok { // if v, ok := jsonvalue["char"]; ok {
if value, ok := v.(string); ok { // if value, ok := v.(string); ok {
colsec.MaskChar = value // colsec.MaskChar = value
} // }
} // }
colSecList = append(colSecList, colsec) // colSecList = append(colSecList, colsec)
} // }
return colSecList, nil return colSecList, nil
} }
@ -296,34 +293,34 @@ func ExampleLoadRowSecurityFromDatabase(pUserID int, pSchema, pTablename string)
UserID: pUserID, UserID: pUserID,
} }
rows, err := DBM.DBConn.Raw(` // rows, err := DBM.DBConn.Raw(`
SELECT r.p_retval, r.p_errmsg, r.p_template, r.p_block // SELECT r.p_retval, r.p_errmsg, r.p_template, r.p_block
FROM core.api_sec_rowtemplate(?, ?, ?) r // FROM core.api_sec_rowtemplate(?, ?, ?) r
`, pSchema, pTablename, pUserID).Rows() // `, pSchema, pTablename, pUserID).Rows()
defer func() { // defer func() {
if rows != nil { // if rows != nil {
rows.Close() // rows.Close()
} // }
}() // }()
if err != nil { // if err != nil {
return record, fmt.Errorf("failed to fetch row security from SQL: %v", err) // return record, fmt.Errorf("failed to fetch row security from SQL: %v", err)
} // }
for rows.Next() { // for rows.Next() {
var retval int // var retval int
var errmsg string // var errmsg string
err = rows.Scan(&retval, &errmsg, &record.Template, &record.HasBlock) // err = rows.Scan(&retval, &errmsg, &record.Template, &record.HasBlock)
if err != nil { // if err != nil {
return record, fmt.Errorf("failed to scan row security: %v", err) // return record, fmt.Errorf("failed to scan row security: %v", err)
} // }
if retval != 0 { // if retval != 0 {
return RowSecurity{}, fmt.Errorf("api_sec_rowtemplate error: %s", errmsg) // return RowSecurity{}, fmt.Errorf("api_sec_rowtemplate error: %s", errmsg)
} // }
} // }
return record, nil return record, nil
} }

View File

@ -146,7 +146,7 @@ func (m *SecurityList) ColumSecurityApplyOnRecord(prevRecord reflect.Value, newR
} }
for _, colsec := range colsecList { for _, colsec := range colsecList {
if !(strings.EqualFold(colsec.Accesstype, "mask") || strings.EqualFold(colsec.Accesstype, "hide")) { if !strings.EqualFold(colsec.Accesstype, "mask") && !strings.EqualFold(colsec.Accesstype, "hide") {
continue continue
} }
lastRecords := interateStruct(prevRecord) lastRecords := interateStruct(prevRecord)
@ -316,7 +316,7 @@ func (m *SecurityList) ApplyColumnSecurity(records reflect.Value, modelType refl
} }
for _, colsec := range colsecList { for _, colsec := range colsecList {
if !(strings.EqualFold(colsec.Accesstype, "mask") || strings.EqualFold(colsec.Accesstype, "hide")) { if !strings.EqualFold(colsec.Accesstype, "mask") && !strings.EqualFold(colsec.Accesstype, "hide") {
continue continue
} }
@ -408,7 +408,7 @@ func (m *SecurityList) ClearSecurity(pUserID int, pSchema, pTablename string) er
} }
for _, cs := range list { for _, cs := range list {
if !(cs.Schema == pSchema && cs.Tablename == pTablename && cs.UserID == pUserID) { if cs.Schema != pSchema && cs.Tablename != pTablename && cs.UserID != pUserID {
filtered = append(filtered, cs) filtered = append(filtered, cs)
} }
} }

View File

@ -4,9 +4,10 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
) )
// SetupSecurityProvider initializes and configures the security provider // SetupSecurityProvider initializes and configures the security provider
@ -31,7 +32,6 @@ import (
// // Step 3: Apply middleware // // Step 3: Apply middleware
// router.Use(mux.MiddlewareFunc(security.AuthMiddleware)) // router.Use(mux.MiddlewareFunc(security.AuthMiddleware))
// router.Use(mux.MiddlewareFunc(security.SetSecurityMiddleware)) // router.Use(mux.MiddlewareFunc(security.SetSecurityMiddleware))
//
func SetupSecurityProvider(handler *restheadspec.Handler, securityList *SecurityList) error { func SetupSecurityProvider(handler *restheadspec.Handler, securityList *SecurityList) error {
// Validate that required callbacks are configured // Validate that required callbacks are configured
if securityList.AuthenticateCallback == nil { if securityList.AuthenticateCallback == nil {