mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-11-13 09:53:53 +00:00
Linting fixes
This commit is contained in:
parent
412bbab560
commit
682716dd31
129
.golangci.json
Normal file
129
.golangci.json
Normal 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"
|
||||
}
|
||||
110
.golangci.yml
110
.golangci.yml
@ -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
|
||||
@ -6,8 +6,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
"github.com/uptrace/bun"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
)
|
||||
|
||||
// BunAdapter adapts Bun to work with our Database interface
|
||||
|
||||
@ -5,8 +5,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
)
|
||||
|
||||
// GormAdapter adapts GORM to work with our Database interface
|
||||
|
||||
@ -3,8 +3,9 @@ package router
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
"github.com/uptrace/bunrouter"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
)
|
||||
|
||||
// BunRouterAdapter adapts uptrace/bunrouter to work with our Router interface
|
||||
|
||||
@ -5,8 +5,9 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/common"
|
||||
)
|
||||
|
||||
// MuxAdapter adapts Gorilla Mux to work with our Router interface
|
||||
|
||||
@ -75,7 +75,7 @@ func Debug(template string, args ...interface{}) {
|
||||
// CatchPanic - Handle panic
|
||||
func CatchPanicCallback(location string, cb func(err any)) {
|
||||
if err := recover(); err != nil {
|
||||
//callstack := debug.Stack()
|
||||
// callstack := debug.Stack()
|
||||
|
||||
if Logger != nil {
|
||||
Error("Panic in %s : %v", location, err)
|
||||
@ -84,7 +84,7 @@ func CatchPanicCallback(location string, cb func(err any)) {
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
//push to sentry
|
||||
// push to sentry
|
||||
// hub := sentry.CurrentHub()
|
||||
// if hub != nil {
|
||||
// evtID := hub.Recover(err)
|
||||
|
||||
@ -69,19 +69,19 @@ func (r *DefaultModelRegistry) RegisterModel(name string, model interface{}) err
|
||||
func (r *DefaultModelRegistry) GetModel(name string) (interface{}, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
|
||||
model, exists := r.models[name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("model %s not found", name)
|
||||
}
|
||||
|
||||
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func (r *DefaultModelRegistry) GetAllModels() map[string]interface{} {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
|
||||
result := make(map[string]interface{})
|
||||
for k, v := range r.models {
|
||||
result[k] = v
|
||||
@ -132,4 +132,4 @@ func GetModels() []interface{} {
|
||||
models = append(models, model)
|
||||
}
|
||||
return models
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,11 +73,11 @@ func GetModelColumnDetail(record reflect.Value) []ModelFieldDetail {
|
||||
ie := strings.Index(gormdetail[ik:], ";")
|
||||
if ie > ik && ik > 0 {
|
||||
fielddetail.SQLName = strings.ToLower(gormdetail)[ik+11 : ik+ie]
|
||||
//fmt.Printf("\r\nforeignkey: %v", fielddetail)
|
||||
// fmt.Printf("\r\nforeignkey: %v", fielddetail)
|
||||
}
|
||||
|
||||
}
|
||||
//";foreignkey:rid_parent;association_foreignkey:id_atevent;save_associations:false;association_autocreate:false;"
|
||||
// ";foreignkey:rid_parent;association_foreignkey:id_atevent;save_associations:false;association_autocreate:false;"
|
||||
|
||||
lst = append(lst, fielddetail)
|
||||
|
||||
|
||||
@ -210,7 +210,7 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
|
||||
// Apply sorting
|
||||
for _, sort := range options.Sort {
|
||||
direction := "ASC"
|
||||
if strings.ToLower(sort.Direction) == "desc" {
|
||||
if strings.EqualFold(sort.Direction, "desc") {
|
||||
direction = "DESC"
|
||||
}
|
||||
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) {
|
||||
w.SetHeader("Content-Type", "application/json")
|
||||
w.WriteJSON(common.Response{
|
||||
err := w.WriteJSON(common.Response{
|
||||
Success: true,
|
||||
Data: data,
|
||||
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{}) {
|
||||
w.SetHeader("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
w.WriteJSON(common.Response{
|
||||
err := w.WriteJSON(common.Response{
|
||||
Success: false,
|
||||
Error: &common.APIError{
|
||||
Code: code,
|
||||
@ -988,6 +991,9 @@ func (h *Handler) sendError(w common.ResponseWriter, status int, code, message s
|
||||
Detail: fmt.Sprintf("%v", details),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("Error sending response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterModel allows registering models at runtime
|
||||
|
||||
@ -23,5 +23,5 @@ func (r GormTableCRUDRequest) GetRequest() string {
|
||||
|
||||
// New interfaces that replace the legacy ones above
|
||||
// These are now defined in database.go:
|
||||
// - TableNameProvider (replaces GormTableNameInterface)
|
||||
// - TableNameProvider (replaces GormTableNameInterface)
|
||||
// - SchemaProvider (replaces GormTableSchemaInterface)
|
||||
|
||||
@ -3,13 +3,14 @@ package resolvespec
|
||||
import (
|
||||
"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/uptrace/bun"
|
||||
"github.com/uptrace/bunrouter"
|
||||
"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
|
||||
|
||||
@ -140,19 +140,19 @@ func (opts *ExtendedRequestOptions) GetCursorFilter(
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Helper: get active cursor (forward or backward)
|
||||
func (opts *ExtendedRequestOptions) getActiveCursor() (id string, direction CursorDirection) {
|
||||
if opts.RequestOptions.CursorForward != "" {
|
||||
return opts.RequestOptions.CursorForward, CursorForward
|
||||
if opts.CursorForward != "" {
|
||||
return opts.CursorForward, CursorForward
|
||||
}
|
||||
if opts.RequestOptions.CursorBackward != "" {
|
||||
return opts.RequestOptions.CursorBackward, CursorBackward
|
||||
if opts.CursorBackward != "" {
|
||||
return opts.CursorBackward, CursorBackward
|
||||
}
|
||||
return "", 0
|
||||
}
|
||||
|
||||
// Helper: extract sort columns
|
||||
func (opts *ExtendedRequestOptions) getSortColumns() []common.SortOption {
|
||||
if opts.RequestOptions.Sort != nil {
|
||||
return opts.RequestOptions.Sort
|
||||
if opts.Sort != nil {
|
||||
return opts.Sort
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ func (h *Handler) handleRead(ctx context.Context, w common.ResponseWriter, id st
|
||||
// Apply sorting
|
||||
for _, sort := range options.Sort {
|
||||
direction := "ASC"
|
||||
if strings.ToLower(sort.Direction) == "desc" {
|
||||
if strings.EqualFold(sort.Direction, "desc") {
|
||||
direction = "DESC"
|
||||
}
|
||||
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
|
||||
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")
|
||||
|
||||
// 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
|
||||
if options.RequestOptions.FetchRowNumber != nil && *options.RequestOptions.FetchRowNumber != "" {
|
||||
if options.FetchRowNumber != nil && *options.FetchRowNumber != "" {
|
||||
pkName := reflection.GetPrimaryKeyName(model)
|
||||
pkValue := *options.RequestOptions.FetchRowNumber
|
||||
pkValue := *options.FetchRowNumber
|
||||
|
||||
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))
|
||||
for _, sort := range options.Sort {
|
||||
direction := "ASC"
|
||||
if strings.ToLower(sort.Direction) == "desc" {
|
||||
if strings.EqualFold(sort.Direction, "desc") {
|
||||
direction = "DESC"
|
||||
}
|
||||
sortParts = append(sortParts, fmt.Sprintf("%s.%s %s", tableName, sort.Column, direction))
|
||||
|
||||
@ -2,7 +2,6 @@ package restheadspec
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@ -59,7 +58,7 @@ func decodeHeaderValue(value string) string {
|
||||
|
||||
// DecodeParam - Decodes parameter string and returns unencoded string
|
||||
func DecodeParam(pStr string) (string, error) {
|
||||
var code string = pStr
|
||||
var code = pStr
|
||||
if strings.HasPrefix(pStr, "ZIP_") {
|
||||
code = strings.ReplaceAll(pStr, "ZIP_", "")
|
||||
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"):
|
||||
h.parseNotSelectFields(&options, decodedValue)
|
||||
case strings.HasPrefix(normalizedKey, "x-clean-json"):
|
||||
options.CleanJSON = strings.ToLower(decodedValue) == "true"
|
||||
options.CleanJSON = strings.EqualFold(decodedValue, "true")
|
||||
|
||||
// Filtering & Search
|
||||
case strings.HasPrefix(normalizedKey, "x-fieldfilter-"):
|
||||
@ -166,9 +165,9 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
|
||||
options.Offset = &offset
|
||||
}
|
||||
case strings.HasPrefix(normalizedKey, "x-cursor-forward"):
|
||||
options.RequestOptions.CursorForward = decodedValue
|
||||
options.CursorForward = decodedValue
|
||||
case strings.HasPrefix(normalizedKey, "x-cursor-backward"):
|
||||
options.RequestOptions.CursorBackward = decodedValue
|
||||
options.CursorBackward = decodedValue
|
||||
|
||||
// Advanced Features
|
||||
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-")
|
||||
options.ComputedQL[colName] = decodedValue
|
||||
case strings.HasPrefix(normalizedKey, "x-distinct"):
|
||||
options.Distinct = strings.ToLower(decodedValue) == "true"
|
||||
options.Distinct = strings.EqualFold(decodedValue, "true")
|
||||
case strings.HasPrefix(normalizedKey, "x-skipcount"):
|
||||
options.SkipCount = strings.ToLower(decodedValue) == "true"
|
||||
options.SkipCount = strings.EqualFold(decodedValue, "true")
|
||||
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"):
|
||||
options.RequestOptions.FetchRowNumber = &decodedValue
|
||||
options.FetchRowNumber = &decodedValue
|
||||
case strings.HasPrefix(normalizedKey, "x-pkrow"):
|
||||
options.PKRow = &decodedValue
|
||||
|
||||
@ -198,7 +197,7 @@ func (h *Handler) parseOptionsFromHeaders(r common.Request) ExtendedRequestOptio
|
||||
|
||||
// Transaction Control
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
func (h *Handler) getColumnTypeFromModel(model interface{}, colName string) reflect.Kind {
|
||||
if model == nil {
|
||||
@ -536,11 +525,6 @@ func isStringType(kind reflect.Kind) bool {
|
||||
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
|
||||
func convertToNumericType(value string, kind reflect.Kind) (interface{}, error) {
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
@ -95,7 +95,7 @@ func (r *HookRegistry) RegisterMultiple(hookTypes []HookType, hook HookFunc) {
|
||||
func (r *HookRegistry) Execute(hookType HookType, ctx *HookContext) error {
|
||||
hooks, exists := r.hooks[hookType]
|
||||
if !exists || len(hooks) == 0 {
|
||||
//logger.Debug("No hooks registered for %s", hookType)
|
||||
// logger.Debug("No hooks registered for %s", hookType)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ func (r *HookRegistry) Execute(hookType HookType, ctx *HookContext) error {
|
||||
}
|
||||
}
|
||||
|
||||
//logger.Debug("All hooks for %s executed successfully", hookType)
|
||||
// logger.Debug("All hooks for %s executed successfully", hookType)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -55,13 +55,14 @@ package restheadspec
|
||||
import (
|
||||
"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/uptrace/bun"
|
||||
"github.com/uptrace/bunrouter"
|
||||
"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
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
DBM "github.com/bitechdev/GoCore/pkg/models"
|
||||
"github.com/bitechdev/ResolveSpec/pkg/logger"
|
||||
// DBM "github.com/bitechdev/GoCore/pkg/models"
|
||||
)
|
||||
|
||||
// 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) {
|
||||
colSecList := make([]ColumnSecurity, 0)
|
||||
|
||||
getExtraFilters := func(pStr string) map[string]string {
|
||||
mp := make(map[string]string, 0)
|
||||
for i, val := range strings.Split(pStr, ",") {
|
||||
if i <= 1 {
|
||||
continue
|
||||
}
|
||||
vals := strings.Split(val, ":")
|
||||
if len(vals) > 1 {
|
||||
mp[vals[0]] = vals[1]
|
||||
}
|
||||
}
|
||||
return mp
|
||||
}
|
||||
// getExtraFilters := func(pStr string) map[string]string {
|
||||
// mp := make(map[string]string, 0)
|
||||
// for i, val := range strings.Split(pStr, ",") {
|
||||
// if i <= 1 {
|
||||
// continue
|
||||
// }
|
||||
// vals := strings.Split(val, ":")
|
||||
// if len(vals) > 1 {
|
||||
// mp[vals[0]] = vals[1]
|
||||
// }
|
||||
// }
|
||||
// return mp
|
||||
// }
|
||||
|
||||
rows, err := DBM.DBConn.Raw(fmt.Sprintf(`
|
||||
SELECT a.rid_secacces, a.control, a.accesstype, a.jsonvalue
|
||||
FROM core.secacces a
|
||||
WHERE a.rid_hub IN (
|
||||
SELECT l.rid_hub_parent
|
||||
FROM core.hub_link l
|
||||
WHERE l.parent_hubtype = 'secgroup'
|
||||
AND l.rid_hub_child = ?
|
||||
)
|
||||
AND control ILIKE '%s.%s%%'
|
||||
`, pSchema, pTablename), pUserID).Rows()
|
||||
// rows, err := DBM.DBConn.Raw(fmt.Sprintf(`
|
||||
// SELECT a.rid_secacces, a.control, a.accesstype, a.jsonvalue
|
||||
// FROM core.secacces a
|
||||
// WHERE a.rid_hub IN (
|
||||
// SELECT l.rid_hub_parent
|
||||
// FROM core.hub_link l
|
||||
// WHERE l.parent_hubtype = 'secgroup'
|
||||
// AND l.rid_hub_child = ?
|
||||
// )
|
||||
// AND control ILIKE '%s.%s%%'
|
||||
// `, pSchema, pTablename), pUserID).Rows()
|
||||
|
||||
defer func() {
|
||||
if rows != nil {
|
||||
rows.Close()
|
||||
}
|
||||
}()
|
||||
// defer func() {
|
||||
// if rows != nil {
|
||||
// rows.Close()
|
||||
// }
|
||||
// }()
|
||||
|
||||
if err != nil {
|
||||
return colSecList, fmt.Errorf("failed to fetch column security from SQL: %v", err)
|
||||
}
|
||||
// if err != nil {
|
||||
// return colSecList, fmt.Errorf("failed to fetch column security from SQL: %v", err)
|
||||
// }
|
||||
|
||||
for rows.Next() {
|
||||
var rid int
|
||||
var jsondata []byte
|
||||
var control, accesstype string
|
||||
// for rows.Next() {
|
||||
// var rid int
|
||||
// var jsondata []byte
|
||||
// var control, accesstype string
|
||||
|
||||
err = rows.Scan(&rid, &control, &accesstype, &jsondata)
|
||||
if err != nil {
|
||||
return colSecList, fmt.Errorf("failed to scan column security: %v", err)
|
||||
}
|
||||
// err = rows.Scan(&rid, &control, &accesstype, &jsondata)
|
||||
// if err != nil {
|
||||
// return colSecList, fmt.Errorf("failed to scan column security: %v", err)
|
||||
// }
|
||||
|
||||
parts := strings.Split(control, ",")
|
||||
ids := strings.Split(parts[0], ".")
|
||||
if len(ids) < 3 {
|
||||
continue
|
||||
}
|
||||
// parts := strings.Split(control, ",")
|
||||
// ids := strings.Split(parts[0], ".")
|
||||
// if len(ids) < 3 {
|
||||
// continue
|
||||
// }
|
||||
|
||||
jsonvalue := make(map[string]interface{})
|
||||
if len(jsondata) > 1 {
|
||||
err = json.Unmarshal(jsondata, &jsonvalue)
|
||||
if err != nil {
|
||||
logger.Error("Failed to parse json: %v", err)
|
||||
}
|
||||
}
|
||||
// jsonvalue := make(map[string]interface{})
|
||||
// if len(jsondata) > 1 {
|
||||
// err = json.Unmarshal(jsondata, &jsonvalue)
|
||||
// if err != nil {
|
||||
// logger.Error("Failed to parse json: %v", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
colsec := ColumnSecurity{
|
||||
Schema: pSchema,
|
||||
Tablename: pTablename,
|
||||
UserID: pUserID,
|
||||
Path: ids[2:],
|
||||
ExtraFilters: getExtraFilters(control),
|
||||
Accesstype: accesstype,
|
||||
Control: control,
|
||||
ID: int(rid),
|
||||
}
|
||||
// colsec := ColumnSecurity{
|
||||
// Schema: pSchema,
|
||||
// Tablename: pTablename,
|
||||
// UserID: pUserID,
|
||||
// Path: ids[2:],
|
||||
// ExtraFilters: getExtraFilters(control),
|
||||
// Accesstype: accesstype,
|
||||
// Control: control,
|
||||
// ID: int(rid),
|
||||
// }
|
||||
|
||||
// Parse masking configuration from JSON
|
||||
if v, ok := jsonvalue["start"]; ok {
|
||||
if value, ok := v.(float64); ok {
|
||||
colsec.MaskStart = int(value)
|
||||
}
|
||||
}
|
||||
// // Parse masking configuration from JSON
|
||||
// if v, ok := jsonvalue["start"]; ok {
|
||||
// if value, ok := v.(float64); ok {
|
||||
// colsec.MaskStart = int(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
if v, ok := jsonvalue["end"]; ok {
|
||||
if value, ok := v.(float64); ok {
|
||||
colsec.MaskEnd = int(value)
|
||||
}
|
||||
}
|
||||
// if v, ok := jsonvalue["end"]; ok {
|
||||
// if value, ok := v.(float64); ok {
|
||||
// colsec.MaskEnd = int(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
if v, ok := jsonvalue["invert"]; ok {
|
||||
if value, ok := v.(bool); ok {
|
||||
colsec.MaskInvert = value
|
||||
}
|
||||
}
|
||||
// if v, ok := jsonvalue["invert"]; ok {
|
||||
// if value, ok := v.(bool); ok {
|
||||
// colsec.MaskInvert = value
|
||||
// }
|
||||
// }
|
||||
|
||||
if v, ok := jsonvalue["char"]; ok {
|
||||
if value, ok := v.(string); ok {
|
||||
colsec.MaskChar = value
|
||||
}
|
||||
}
|
||||
// if v, ok := jsonvalue["char"]; ok {
|
||||
// if value, ok := v.(string); ok {
|
||||
// colsec.MaskChar = value
|
||||
// }
|
||||
// }
|
||||
|
||||
colSecList = append(colSecList, colsec)
|
||||
}
|
||||
// colSecList = append(colSecList, colsec)
|
||||
// }
|
||||
|
||||
return colSecList, nil
|
||||
}
|
||||
@ -296,34 +293,34 @@ func ExampleLoadRowSecurityFromDatabase(pUserID int, pSchema, pTablename string)
|
||||
UserID: pUserID,
|
||||
}
|
||||
|
||||
rows, err := DBM.DBConn.Raw(`
|
||||
SELECT r.p_retval, r.p_errmsg, r.p_template, r.p_block
|
||||
FROM core.api_sec_rowtemplate(?, ?, ?) r
|
||||
`, pSchema, pTablename, pUserID).Rows()
|
||||
// rows, err := DBM.DBConn.Raw(`
|
||||
// SELECT r.p_retval, r.p_errmsg, r.p_template, r.p_block
|
||||
// FROM core.api_sec_rowtemplate(?, ?, ?) r
|
||||
// `, pSchema, pTablename, pUserID).Rows()
|
||||
|
||||
defer func() {
|
||||
if rows != nil {
|
||||
rows.Close()
|
||||
}
|
||||
}()
|
||||
// defer func() {
|
||||
// if rows != nil {
|
||||
// rows.Close()
|
||||
// }
|
||||
// }()
|
||||
|
||||
if err != nil {
|
||||
return record, fmt.Errorf("failed to fetch row security from SQL: %v", err)
|
||||
}
|
||||
// if err != nil {
|
||||
// return record, fmt.Errorf("failed to fetch row security from SQL: %v", err)
|
||||
// }
|
||||
|
||||
for rows.Next() {
|
||||
var retval int
|
||||
var errmsg string
|
||||
// for rows.Next() {
|
||||
// var retval int
|
||||
// var errmsg string
|
||||
|
||||
err = rows.Scan(&retval, &errmsg, &record.Template, &record.HasBlock)
|
||||
if err != nil {
|
||||
return record, fmt.Errorf("failed to scan row security: %v", err)
|
||||
}
|
||||
// err = rows.Scan(&retval, &errmsg, &record.Template, &record.HasBlock)
|
||||
// if err != nil {
|
||||
// return record, fmt.Errorf("failed to scan row security: %v", err)
|
||||
// }
|
||||
|
||||
if retval != 0 {
|
||||
return RowSecurity{}, fmt.Errorf("api_sec_rowtemplate error: %s", errmsg)
|
||||
}
|
||||
}
|
||||
// if retval != 0 {
|
||||
// return RowSecurity{}, fmt.Errorf("api_sec_rowtemplate error: %s", errmsg)
|
||||
// }
|
||||
// }
|
||||
|
||||
return record, nil
|
||||
}
|
||||
|
||||
@ -7,9 +7,9 @@ import (
|
||||
|
||||
const (
|
||||
// Context keys for user information
|
||||
UserIDKey = "user_id"
|
||||
UserRolesKey = "user_roles"
|
||||
UserTokenKey = "user_token"
|
||||
UserIDKey = "user_id"
|
||||
UserRolesKey = "user_roles"
|
||||
UserTokenKey = "user_token"
|
||||
)
|
||||
|
||||
// AuthMiddleware extracts user authentication from request and adds to context
|
||||
|
||||
@ -146,7 +146,7 @@ func (m *SecurityList) ColumSecurityApplyOnRecord(prevRecord reflect.Value, newR
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
lastRecords := interateStruct(prevRecord)
|
||||
@ -316,7 +316,7 @@ func (m *SecurityList) ApplyColumnSecurity(records reflect.Value, modelType refl
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -408,7 +408,7 @@ func (m *SecurityList) ClearSecurity(pUserID int, pSchema, pTablename string) er
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
|
||||
"github.com/gorilla/mux"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
|
||||
)
|
||||
|
||||
// SetupSecurityProvider initializes and configures the security provider
|
||||
@ -31,7 +32,6 @@ import (
|
||||
// // Step 3: Apply middleware
|
||||
// router.Use(mux.MiddlewareFunc(security.AuthMiddleware))
|
||||
// router.Use(mux.MiddlewareFunc(security.SetSecurityMiddleware))
|
||||
//
|
||||
func SetupSecurityProvider(handler *restheadspec.Handler, securityList *SecurityList) error {
|
||||
// Validate that required callbacks are configured
|
||||
if securityList.AuthenticateCallback == nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user