Compare commits

...

9 Commits

Author SHA1 Message Date
Jamie Curnow
72e4a78fbf Update backend packages 2025-07-03 11:08:36 +10:00
Jamie Curnow
f3182c1258 Use previous version of powerdns image, newer version is broken 2025-01-07 11:19:15 +10:00
Jamie Curnow
9d3c06dbe4 Support containerized cpu limits 2024-12-02 08:44:28 +10:00
Jamie Curnow
152b7666d8 New lint rules 2024-11-21 19:07:36 +10:00
Jamie Curnow
4e6d65645f Fix cypress oauth test one more time 2024-11-13 14:21:16 +10:00
Jamie Curnow
8434b9fce4 Fix unit test 2024-11-13 13:50:44 +10:00
jc21
f4bd65dd2c Fix oauth cypress test 2024-11-13 13:38:33 +10:00
Jamie Curnow
a856c4d6e1 Use new instance of autentik db made in dev 2024-11-13 12:46:43 +10:00
Jamie Curnow
2f334b5f9f Fix ci clearing users not clearing auth 2024-11-13 12:38:59 +10:00
98 changed files with 547 additions and 432 deletions

View File

@@ -1,33 +1,80 @@
---
linters: linters:
enable: enable:
# Prevents against memory leaks in production caused by not closing
# file handle
- bodyclose - bodyclose
# Detects cloned code. DRY is good programming practice. Can cause issues
# with testing code where simplicity is preferred over duplication.
# Disabled for test code.
# - dupl
# Detects unchecked errors in go programs. These unchecked errors can be
# critical bugs in some cases.
- errcheck - errcheck
# Simplifies go code.
- gosimple - gosimple
# Controls Go package import order and makes it always deterministic.
- gci
# Reports suspicious constructs, maintained by goteam. e.g. Printf unused
# params not caught at compile time.
- govet - govet
# Detect security issues with gocode. Use of secrets in code or obsolete
# security algorithms. It's imaged heuristic methods are used in finding
# problems. If issues with rules are found particular rules can be disabled
# as required. Could possibility cause issues with testing.
# Disabled for test code.
- gosec - gosec
# Detect repeated strings that could be replaced by a constant
- goconst - goconst
# Misc linters missing from other projects. Grouped into 3 categories
# diagnostics, style and performance
- gocritic - gocritic
# Limits code cyclomatic complexity
- gocyclo - gocyclo
# Detects if code needs to be gofmt'd
- gofmt - gofmt
# Detects unused go package imports
- goimports - goimports
# Detects style mistakes not correctness. Golint is meant to carry out the
# stylistic conventions put forth in Effective Go and CodeReviewComments.
# golint has false positives and false negatives and can be tweaked.
- revive
# Detects ineffectual assignments in code
- ineffassign - ineffassign
# Reports long lines
# - lll
# Detect commonly misspelled english words in comments
- misspell - misspell
# Detect naked returns on non-trivial functions, and conform with
# Go CodeReviewComments
- nakedret - nakedret
# Detect slice allocations that can be preallocated
- prealloc - prealloc
#- revive # Misc collection of static analysis tools
- staticcheck - staticcheck
# Detects unused struct fields
# - structcheck
# Parses and typechecks the code like the go compiler
- typecheck - typecheck
# Detects unused constants, variables, functions and types
- unused - unused
# Remove unnecessary type conversions
- unconvert - unconvert
# Remove unnecessary(unused) function parameters
- unparam - unparam
linters-settings: linters-settings:
gosec:
excludes:
- G115
errcheck: errcheck:
exclude-functions: exclude-functions:
- fmt.Fprint - fmt.Fprint
- fmt.Fprintf - fmt.Fprintf
gci:
sections:
- standard # Standard section: captures all standard packages.
- localmodule # Local module section: contains all local packages.
# - prefix(gogs.jc21.com) # Prefixed gerrit.lan packages (jumgo).
- default # Everything else (github.com, golang.org, etc).
- blank # Blank section: contains all blank imports.
custom-order: true
goconst: goconst:
# minimal length of string constant # minimal length of string constant
# default: 3 # default: 3
@@ -35,21 +82,73 @@ linters-settings:
# minimum number of occurrences of string constant # minimum number of occurrences of string constant
# default: 3 # default: 3
min-occurences: 2 min-occurences: 2
misspell: revive:
locale: UK enable-all-rules: true
ignore-words: rules:
- color - name: unchecked-type-assertion
disabled: true
# handled by goconst
- name: add-constant
disabled: true
# cant limit this arbitrarily
- name: argument-limit
disabled: true
# handled by gocyclo
- name: cognitive-complexity
disabled: true
# false positive for Exported vs non-exported functions of the same name
- name: confusing-naming
disabled: true
# false positives for "" - which is the nil value of a string (also 0)
- name: confusing-results
disabled: true
# handled by gocyclo
- name: cyclomatic
disabled: true
# have comments on exported functions but not on vars/types/constants
- name: exported
arguments:
- "disableChecksOnConstants"
- "disableChecksOnTypes"
- "disableChecksOnVariables"
# false positives on bool params
- name: flag-parameter
disabled: true
# extreme verticalization can happen
- name: function-length
disabled: true
# can false positive for non-getters
- name: get-return
disabled: true
# only allows lowercase names
- name: import-alias-naming
disabled: true
# handled by lll
- name: line-length-limit
disabled: true
# don't want to arbitrarily limit this
# many places have specific model.go files to contain all structs
- name: max-public-structs
disabled: true
# disable package-comments
- name: package-comments
disabled: true
# this is handled by errcheck
- name: unhandled-error
disabled: true
- name: function-result-limit
disabled: true
issues: issues:
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3. # Maximum count of issues with the same text. Set to 0 to disable. Default
# We have chosen an arbitrary value that works based on practical usage. # is 3. We have chosen an arbitrary value that works based on practical usage.
max-same: 20 max-same: 20
# See cmdline flag documentation for more info about default excludes --exclude-use-default # See cmdline flag documentation for more info about default excludes
# Nothing is excluded by default # --exclude-use-default. Nothing is excluded by default
exclude-use-default: false exclude-use-default: false
# Excluding configuration per-path, per-linter, per-text and per-source # Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules: exclude-rules:
# Exclude some linters from running on tests files. # TODO: Add examples why this is good # Exclude some linters from running on tests files.
# TODO: Add examples why this is good
- path: _test\.go - path: _test\.go
linters: linters:
# Tests should be simple? Add example why this is good? # Tests should be simple? Add example why this is good?
@@ -61,3 +160,7 @@ issues:
# Hard coded example tokens, SQL injection and other bad practices may # Hard coded example tokens, SQL injection and other bad practices may
# want to be tested # want to be tested
- gosec - gosec
# Test data can long
# - lll
run:
go: '1.23'

View File

@@ -15,6 +15,9 @@ import (
"npm/internal/jobqueue" "npm/internal/jobqueue"
"npm/internal/jwt" "npm/internal/jwt"
"npm/internal/logger" "npm/internal/logger"
// properly respect available cpu cores
_ "go.uber.org/automaxprocs"
) )
var commit string var commit string

View File

@@ -1,6 +1,8 @@
module npm module npm
go 1.23 go 1.24
toolchain go1.24.3
require ( require (
github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/DATA-DOG/go-sqlmock v1.5.2
@@ -11,24 +13,25 @@ require (
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e
github.com/fatih/color v1.18.0 github.com/fatih/color v1.18.0
github.com/glebarez/sqlite v1.11.0 github.com/glebarez/sqlite v1.11.0
github.com/go-chi/chi/v5 v5.1.0 github.com/go-chi/chi/v5 v5.2.2
github.com/go-chi/cors v1.2.1 github.com/go-chi/cors v1.2.2
github.com/go-chi/jwtauth/v5 v5.3.1 github.com/go-chi/jwtauth/v5 v5.3.3
github.com/go-ldap/ldap/v3 v3.4.8 github.com/go-ldap/ldap/v3 v3.4.11
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec github.com/jc21/go-sse v1.7.0
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760 github.com/jc21/jsref v0.0.0-20250501111625-0ce4620b7d96
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/qri-io/jsonschema v0.2.1 github.com/qri-io/jsonschema v0.2.1
github.com/rotisserie/eris v0.5.4 github.com/rotisserie/eris v0.5.4
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.10.0
github.com/vrischmann/envconfig v1.3.0 github.com/vrischmann/envconfig v1.4.1
go.uber.org/automaxprocs v1.6.0
go.uber.org/goleak v1.3.0 go.uber.org/goleak v1.3.0
golang.org/x/crypto v0.29.0 golang.org/x/crypto v0.39.0
golang.org/x/oauth2 v0.24.0 golang.org/x/oauth2 v0.30.0
gorm.io/datatypes v1.2.4 gorm.io/datatypes v1.2.6
gorm.io/driver/mysql v1.5.7 gorm.io/driver/mysql v1.6.0
gorm.io/driver/postgres v1.5.9 gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.25.12 gorm.io/gorm v1.30.0
gorm.io/plugin/soft_delete v1.2.1 gorm.io/plugin/soft_delete v1.2.1
) )
@@ -40,7 +43,7 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.3 // indirect github.com/goccy/go-json v0.10.3 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
@@ -56,7 +59,7 @@ require (
github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c // indirect github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c // indirect
github.com/lestrrat-go/jwx/v2 v2.1.2 // indirect github.com/lestrrat-go/jwx/v2 v2.1.3 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lestrrat-go/pdebug/v3 v3.0.1 // indirect github.com/lestrrat-go/pdebug/v3 v3.0.1 // indirect
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb // indirect github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb // indirect
@@ -72,11 +75,11 @@ require (
github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/asm v1.2.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/mod v0.22.0 // indirect golang.org/x/mod v0.25.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.27.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/text v0.26.0 // indirect
golang.org/x/tools v0.26.0 // indirect golang.org/x/tools v0.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.3.0 // indirect lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.41.0 // indirect modernc.org/cc/v3 v3.41.0 // indirect

View File

@@ -30,18 +30,16 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/jwtauth/v5 v5.3.3 h1:50Uzmacu35/ZP9ER2Ht6SazwPsnLQ9LRJy6zTZJpHEo=
github.com/go-chi/jwtauth/v5 v5.3.1 h1:1ePWrjVctvp1tyBq5b/2ER8Th/+RbYc7x4qNsc5rh5A= github.com/go-chi/jwtauth/v5 v5.3.3/go.mod h1:O4QvPRuZLZghl9WvfVaON+ARfGzpD2PBX/QY5vUz7aQ=
github.com/go-chi/jwtauth/v5 v5.3.1/go.mod h1:6Fl2RRmWXs3tJYE1IQGX81FsPoGqDwq9c15j52R5q80= github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ= github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
@@ -56,9 +54,6 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -71,10 +66,10 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jc21/dbmate/v2 v2.0.0-20230527023241-0aaa124cc0f1 h1:WEZwsDG5eXdgh0NfA9SpuShOP6rJCah22ihvZsaoimM= github.com/jc21/dbmate/v2 v2.0.0-20230527023241-0aaa124cc0f1 h1:WEZwsDG5eXdgh0NfA9SpuShOP6rJCah22ihvZsaoimM=
github.com/jc21/dbmate/v2 v2.0.0-20230527023241-0aaa124cc0f1/go.mod h1:XAPcHsokw7nyvFbuN9FdcYb8JSEUTaJDFYOirnNxEvc= github.com/jc21/dbmate/v2 v2.0.0-20230527023241-0aaa124cc0f1/go.mod h1:XAPcHsokw7nyvFbuN9FdcYb8JSEUTaJDFYOirnNxEvc=
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec h1:KKntwkZlM2w/88QiDyAeZ4th8grqtituzMW8qyapYzc= github.com/jc21/go-sse v1.7.0 h1:Lavb7FGssS2UdJMK1P3r4rQJgg2JZx7BINi8pd/QzKg=
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec/go.mod h1:4v5Xmm0eYuaWqKJ63XUV5YfQPoxtId3DgDytbnWhi+s= github.com/jc21/go-sse v1.7.0/go.mod h1:dbA0LtDgvSEhlAXz+meN1KAcdvcCLiF0aVdhjhZjbGI=
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760 h1:7wxq2DIgtO36KLrFz1RldysO0WVvcYsD49G9tyAs01k= github.com/jc21/jsref v0.0.0-20250501111625-0ce4620b7d96 h1:LzBXyNdALQHC7DUy8PE7IFTihmnSRop4Ps2cBIr/WP8=
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760/go.mod h1:yIq2t51OJgVsdRlPY68NAnyVdBH0kYXxDTFtUxOap80= github.com/jc21/jsref v0.0.0-20250501111625-0ce4620b7d96/go.mod h1:Vno1sw0yqqImXnYy3q6ueIG+h+Vwwfbkfw9DTHCrHfY=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
@@ -102,8 +97,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kyoh86/richgo v0.3.8/go.mod h1:2C8POkF1H04iTOG2Tp1yyZhspCME9nN3cir3VXJ02II=
github.com/kyoh86/xdg v1.2.0/go.mod h1:/mg8zwu1+qe76oTFUBnyS7rJzk7LLC0VGEzJyJ19DHs=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
@@ -114,31 +107,27 @@ github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzlt
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c h1:pGh5EFIfczeDHwgMHgfwjhZzL+8/E3uZF6T7vER/W8c= github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c h1:pGh5EFIfczeDHwgMHgfwjhZzL+8/E3uZF6T7vER/W8c=
github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c/go.mod h1:xw2Gm4Mg+ST9s8fHR1VkUIyOJMJnSloRZlPQB+wyVpY= github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c/go.mod h1:xw2Gm4Mg+ST9s8fHR1VkUIyOJMJnSloRZlPQB+wyVpY=
github.com/lestrrat-go/jwx/v2 v2.1.2 h1:6poete4MPsO8+LAEVhpdrNI4Xp2xdiafgl2RD89moBc= github.com/lestrrat-go/jwx/v2 v2.1.3 h1:Ud4lb2QuxRClYAmRleF50KrbKIoM1TddXgBrneT5/Jo=
github.com/lestrrat-go/jwx/v2 v2.1.2/go.mod h1:pO+Gz9whn7MPdbsqSJzG8TlEpMZCwQDXnFJ+zsUVh8Y= github.com/lestrrat-go/jwx/v2 v2.1.3/go.mod h1:q6uFgbgZfEmQrfJfrCo90QcQOcXFMfbI/fO0NqRtvZo=
github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/pdebug/v3 v3.0.1 h1:3G5sX/aw/TbMTtVc9U7IHBWRZtMvwvBziF1e4HoQtv8= github.com/lestrrat-go/pdebug/v3 v3.0.1 h1:3G5sX/aw/TbMTtVc9U7IHBWRZtMvwvBziF1e4HoQtv8=
github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4= github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4=
github.com/lestrrat-go/structinfo v0.0.0-20190212233437-acd51874663b/go.mod h1:s2U6PowV3/Jobkx/S9d0XiPwOzs6niW3DIouw+7nZC8=
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb h1:DDg5u5lk2v8O8qxs8ecQkMUBj3tLW6wkSLzxxOyi1Ig= github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb h1:DDg5u5lk2v8O8qxs8ecQkMUBj3tLW6wkSLzxxOyi1Ig=
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb/go.mod h1:i+E8Uf04vf2QjOWyJdGY75vmG+4rxiZW2kIj1lTB5mo= github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb/go.mod h1:i+E8Uf04vf2QjOWyJdGY75vmG+4rxiZW2kIj1lTB5mo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -148,11 +137,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA= github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA=
github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0= github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0=
github.com/qri-io/jsonschema v0.2.1/go.mod h1:g7DPkiOsK1xv6T/Ao5scXRkd+yTFygcANPBaaqW+VrI= github.com/qri-io/jsonschema v0.2.1/go.mod h1:g7DPkiOsK1xv6T/Ao5scXRkd+yTFygcANPBaaqW+VrI=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
@@ -170,119 +160,67 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/vrischmann/envconfig v1.3.0 h1:4XIvQTXznxmWMnjouj0ST5lFo/WAYf5Exgl3x82crEk= github.com/vrischmann/envconfig v1.4.1 h1:fucz2HsoAkJCLgIngWdWqLNxNjdWD14zfrLF6EQPdY4=
github.com/vrischmann/envconfig v1.3.0/go.mod h1:bbvxFYJdRSpXrhS63mBFtKJzkDiNkyArOLXtY6q0kuI= github.com/vrischmann/envconfig v1.4.1/go.mod h1:cX3p+/PEssil6fWwzIS7kf8iFpli3giuxXGHxckucYc=
github.com/wacul/ptr v1.0.0/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w= github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4= github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4=
gitlab.com/jc21com/sqlite v1.22.2-0.20230527022643-b56cedb3bc85 h1:NPHauobrOymc80Euu+e0tsMyXcdtLCX5bQPKX5zsI38= gitlab.com/jc21com/sqlite v1.22.2-0.20230527022643-b56cedb3bc85 h1:NPHauobrOymc80Euu+e0tsMyXcdtLCX5bQPKX5zsI38=
gitlab.com/jc21com/sqlite v1.22.2-0.20230527022643-b56cedb3bc85/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= gitlab.com/jc21com/sqlite v1.22.2-0.20230527022643-b56cedb3bc85/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/datatypes v1.2.4 h1:uZmGAcK/QZ0uyfCuVg0VQY1ZmV9h1fuG0tMwKByO1z4= gorm.io/datatypes v1.2.6 h1:KafLdXvFUhzNeL2ncm03Gl3eTLONQfNKZ+wJ+9Y4Nck=
gorm.io/datatypes v1.2.4/go.mod h1:f4BsLcFAX67szSv8svwLRjklArSHAvHLeE3pXAS5DZI= gorm.io/datatypes v1.2.6/go.mod h1:M2iO+6S3hhi4nAyYe444Pcb0dcIiOMJ7QHaUXxyiNZY=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c= gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= gorm.io/driver/sqlserver v1.6.0 h1:VZOBQVsVhkHU/NzNhRJKoANt5pZGQAS1Bwc6m6dgfnc=
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/driver/sqlserver v1.6.0/go.mod h1:WQzt4IJo/WHKnckU9jXBLMJIVNMVeTu25dnOzehntWw=
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU= gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU=
gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk= gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=

View File

@@ -3,17 +3,17 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
h "npm/internal/api/http"
"npm/internal/errors"
"npm/internal/logger"
"slices" "slices"
"time" "time"
c "npm/internal/api/context" c "npm/internal/api/context"
h "npm/internal/api/http"
"npm/internal/entity/auth" "npm/internal/entity/auth"
"npm/internal/entity/setting" "npm/internal/entity/setting"
"npm/internal/entity/user" "npm/internal/entity/user"
"npm/internal/errors"
njwt "npm/internal/jwt" njwt "npm/internal/jwt"
"npm/internal/logger"
"gorm.io/gorm" "gorm.io/gorm"
) )

View File

@@ -151,7 +151,7 @@ func getCertificateFromRequest(w http.ResponseWriter, r *http.Request) *certific
// fillObjectFromBody has some reusable code for all endpoints that // fillObjectFromBody has some reusable code for all endpoints that
// have a certificate id in the url. it will write errors to the output. // have a certificate id in the url. it will write errors to the output.
func fillObjectFromBody(w http.ResponseWriter, r *http.Request, validationSchema string, o interface{}) bool { func fillObjectFromBody(w http.ResponseWriter, r *http.Request, validationSchema string, o any) bool {
bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte) bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte)
if validationSchema != "" { if validationSchema != "" {
@@ -176,10 +176,10 @@ func fillObjectFromBody(w http.ResponseWriter, r *http.Request, validationSchema
return true return true
} }
func configureCertificate(c certificate.Model) { func configureCertificate(cert certificate.Model) {
err := jobqueue.AddJob(jobqueue.Job{ err := jobqueue.AddJob(jobqueue.Job{
Name: "RequestCertificate", Name: "RequestCertificate",
Action: c.Request, Action: cert.Request,
}) })
if err != nil { if err != nil {
logger.Error("ConfigureCertificateError", err) logger.Error("ConfigureCertificateError", err)

View File

@@ -2,6 +2,7 @@ package handler
import ( import (
"net/http" "net/http"
h "npm/internal/api/http" h "npm/internal/api/http"
"npm/internal/config" "npm/internal/config"
) )

View File

@@ -2,6 +2,7 @@ package handler
import ( import (
"net/http" "net/http"
"npm/internal/acme" "npm/internal/acme"
h "npm/internal/api/http" h "npm/internal/api/http"
"npm/internal/config" "npm/internal/config"

View File

@@ -56,7 +56,7 @@ func getQueryVarInt(r *http.Request, varName string, required bool, defaultValue
} }
func getURLParamInt(r *http.Request, varName string) (uint, error) { func getURLParamInt(r *http.Request, varName string) (uint, error) {
var defaultValue uint = 0 var defaultValue uint
required := true required := true
paramStr := chi.URLParam(r, varName) paramStr := chi.URLParam(r, varName)

View File

@@ -3,9 +3,10 @@ package handler
import ( import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"npm/internal/model"
"testing" "testing"
"npm/internal/model"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@@ -192,7 +192,7 @@ func GetHostNginxConfig(format string) func(http.ResponseWriter, *http.Request)
return return
} }
if format == "text" { if format == "text" {
h.ResultResponseText(w, r, http.StatusOK, content) h.ResultResponseText(w, http.StatusOK, content)
return return
} }
h.ResultResponseJSON(w, r, http.StatusOK, content) h.ResultResponseJSON(w, r, http.StatusOK, content)
@@ -202,11 +202,11 @@ func GetHostNginxConfig(format string) func(http.ResponseWriter, *http.Request)
} }
} }
func configureHost(h host.Model) { func configureHost(hst host.Model) {
err := jobqueue.AddJob(jobqueue.Job{ err := jobqueue.AddJob(jobqueue.Job{
Name: "NginxConfigureHost", Name: "NginxConfigureHost",
Action: func() error { Action: func() error {
return nginx.ConfigureHost(h) return nginx.ConfigureHost(hst)
}, },
}) })
if err != nil { if err != nil {

View File

@@ -12,7 +12,7 @@ import (
"npm/internal/config" "npm/internal/config"
"npm/internal/logger" "npm/internal/logger"
jsref "github.com/jc21/jsref" "github.com/jc21/jsref"
"github.com/jc21/jsref/provider" "github.com/jc21/jsref/provider"
) )
@@ -24,7 +24,7 @@ var (
// Schema simply reads the swagger schema from disk and returns is raw // Schema simply reads the swagger schema from disk and returns is raw
// Route: GET /schema // Route: GET /schema
func Schema() func(http.ResponseWriter, *http.Request) { func Schema() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
fmt.Fprint(w, string(getSchema())) fmt.Fprint(w, string(getSchema()))
@@ -42,8 +42,8 @@ func getSchema() []byte {
swaggerSchema = []byte(strings.ReplaceAll(string(swaggerSchema), "{{VERSION}}", config.Version)) swaggerSchema = []byte(strings.ReplaceAll(string(swaggerSchema), "{{VERSION}}", config.Version))
// Dereference the JSON Schema: // Dereference the JSON Schema:
var schema interface{} var sch any
if err := json.Unmarshal(swaggerSchema, &schema); err != nil { if err := json.Unmarshal(swaggerSchema, &sch); err != nil {
logger.Error("SwaggerUnmarshalError", err) logger.Error("SwaggerUnmarshalError", err)
return nil return nil
} }
@@ -55,7 +55,7 @@ func getSchema() []byte {
logger.Error("SchemaProviderError", err) logger.Error("SchemaProviderError", err)
} }
result, err := resolver.Resolve(schema, "", []jsref.Option{jsref.WithRecursiveResolution(true)}...) result, err := resolver.Resolve(sch, "", []jsref.Option{jsref.WithRecursiveResolution(true)}...)
if err != nil { if err != nil {
logger.Error("SwaggerResolveError", err) logger.Error("SwaggerResolveError", err)
} else { } else {

View File

@@ -95,7 +95,7 @@ func CreateUpstream() func(http.ResponseWriter, *http.Request) {
} }
} }
// UpdateHost updates a host // UpdateUpstream updates a stream
// Route: PUT /upstreams/{upstreamID} // Route: PUT /upstreams/{upstreamID}
func UpdateUpstream() func(http.ResponseWriter, *http.Request) { func UpdateUpstream() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
@@ -167,7 +167,7 @@ func DeleteUpstream() func(http.ResponseWriter, *http.Request) {
} }
} }
// GetHostNginxConfig will return a Host's nginx config from disk // GetUpstreamNginxConfig will return a Host's nginx config from disk
// Route: GET /upstreams/{upstreamID}/nginx-config // Route: GET /upstreams/{upstreamID}/nginx-config
// Route: GET /upstreams/{upstreamID}/nginx-config.txt // Route: GET /upstreams/{upstreamID}/nginx-config.txt
func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Request) { func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
@@ -191,7 +191,7 @@ func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Reque
return return
} }
if format == "text" { if format == "text" {
h.ResultResponseText(w, r, http.StatusOK, content) h.ResultResponseText(w, http.StatusOK, content)
return return
} }
h.ResultResponseJSON(w, r, http.StatusOK, content) h.ResultResponseJSON(w, r, http.StatusOK, content)

View File

@@ -21,19 +21,19 @@ var (
// Response interface for standard API results // Response interface for standard API results
type Response struct { type Response struct {
Result interface{} `json:"result"` Result any `json:"result"`
Error interface{} `json:"error,omitempty"` Error any `json:"error,omitempty"`
} }
// ErrorResponse interface for errors returned via the API // ErrorResponse interface for errors returned via the API
type ErrorResponse struct { type ErrorResponse struct {
Code interface{} `json:"code"` Code any `json:"code"`
Message interface{} `json:"message"` Message any `json:"message"`
Invalid interface{} `json:"invalid,omitempty"` Invalid any `json:"invalid,omitempty"`
} }
// ResultResponseJSON will write the result as json to the http output // ResultResponseJSON will write the result as json to the http output
func ResultResponseJSON(w http.ResponseWriter, r *http.Request, status int, result interface{}) { func ResultResponseJSON(w http.ResponseWriter, r *http.Request, status int, result any) {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(status) w.WriteHeader(status)
@@ -77,7 +77,7 @@ func ResultSchemaErrorJSON(w http.ResponseWriter, r *http.Request, errs []jsonsc
} }
// ResultErrorJSON will format the result as a standard error object and send it for output // ResultErrorJSON will format the result as a standard error object and send it for output
func ResultErrorJSON(w http.ResponseWriter, r *http.Request, status int, message string, extended interface{}) { func ResultErrorJSON(w http.ResponseWriter, r *http.Request, status int, message string, extended any) {
errorResponse := ErrorResponse{ errorResponse := ErrorResponse{
Code: status, Code: status,
Message: message, Message: message,
@@ -98,7 +98,7 @@ func NotFound(w http.ResponseWriter, r *http.Request) {
} }
// ResultResponseText will write the result as text to the http output // ResultResponseText will write the result as text to the http output
func ResultResponseText(w http.ResponseWriter, r *http.Request, status int, content string) { func ResultResponseText(w http.ResponseWriter, status int, content string) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(status) w.WriteHeader(status)
fmt.Fprint(w, content) fmt.Fprint(w, content)

View File

@@ -21,7 +21,7 @@ func TestResultResponseJSON(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
status int status int
given interface{} given any
want string want string
}{ }{
{ {
@@ -34,7 +34,7 @@ func TestResultResponseJSON(t *testing.T) {
name: "detailed response", name: "detailed response",
status: http.StatusBadRequest, status: http.StatusBadRequest,
given: user.Model{ given: user.Model{
ModelBase: model.ModelBase{ID: 10}, Base: model.Base{ID: 10},
Email: "me@example.com", Email: "me@example.com",
Name: "John Doe", Name: "John Doe",
}, },
@@ -118,7 +118,7 @@ func TestResultErrorJSON(t *testing.T) {
name string name string
status int status int
message string message string
extended interface{} extended any
want string want string
}{ }{
{ {
@@ -180,9 +180,8 @@ func TestResultResponseText(t *testing.T) {
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
t.Run("basic test", func(t *testing.T) { t.Run("basic test", func(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/anything", nil)
w := httptest.NewRecorder() w := httptest.NewRecorder()
ResultResponseText(w, r, http.StatusOK, "omg this works") ResultResponseText(w, http.StatusOK, "omg this works")
res := w.Result() res := w.Result()
defer res.Body.Close() defer res.Body.Close()
body, err := io.ReadAll(res.Body) body, err := io.ReadAll(res.Body)

View File

@@ -15,7 +15,7 @@ func TestAccessControl(t *testing.T) {
// goleak is used to detect goroutine leaks // goleak is used to detect goroutine leaks
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
}) })

View File

@@ -18,6 +18,6 @@ func AuthCacheInit() {
} }
// AuthCacheSet will store the item in memory for the expiration time // AuthCacheSet will store the item in memory for the expiration time
func AuthCacheSet(k string, x interface{}) { func AuthCacheSet(k string, x any) {
AuthCache.Set(k, x, cache.DefaultExpiration) AuthCache.Set(k, x, cache.DefaultExpiration)
} }

View File

@@ -26,7 +26,7 @@ func TestBodyContext(t *testing.T) {
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
// Create a test handler that checks the context for the body data // Create a test handler that checks the context for the body data
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
bodyData := r.Context().Value(c.BodyCtxKey).([]byte) bodyData := r.Context().Value(c.BodyCtxKey).([]byte)
assert.Equal(t, body, bodyData) assert.Equal(t, body, bodyData)
}) })

View File

@@ -15,7 +15,7 @@ func TestCors(t *testing.T) {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Cors(r)) r.Use(middleware.Cors(r))
r.Get("/test", func(w http.ResponseWriter, r *http.Request) { r.Get("/test", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("test")) w.Write([]byte("test"))
}) })
@@ -48,7 +48,7 @@ func TestOptions(t *testing.T) {
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Options(r)) r.Use(middleware.Options(r))
r.Get("/test", func(w http.ResponseWriter, r *http.Request) { r.Get("/test", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("test")) w.Write([]byte("test"))
}) })

View File

@@ -5,11 +5,11 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/stretchr/testify/assert"
"go.uber.org/goleak"
"npm/internal/api/middleware" "npm/internal/api/middleware"
"npm/internal/config" "npm/internal/config"
"github.com/stretchr/testify/assert"
"go.uber.org/goleak"
) )
func TestEnforceSetup(t *testing.T) { func TestEnforceSetup(t *testing.T) {
@@ -37,7 +37,7 @@ func TestEnforceSetup(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
config.IsSetup = tt.isSetup config.IsSetup = tt.isSetup
handler := middleware.EnforceSetup()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := middleware.EnforceSetup()(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
})) }))

View File

@@ -23,7 +23,7 @@ func TestExpansion(t *testing.T) {
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
expand := middleware.GetExpandFromContext(r) expand := middleware.GetExpandFromContext(r)
assert.Equal(t, []string{"item1", "item2"}, expand) assert.Equal(t, []string{"item1", "item2"}, expand)
}) })
@@ -39,7 +39,7 @@ func TestExpansion(t *testing.T) {
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
expand := middleware.GetExpandFromContext(r) expand := middleware.GetExpandFromContext(r)
assert.Nil(t, expand) assert.Nil(t, expand)
}) })

View File

@@ -21,7 +21,7 @@ import (
// and the sort parameter is valid as well. // and the sort parameter is valid as well.
// After we have determined what the Filters are to be, they are saved on the Context // After we have determined what the Filters are to be, they are saved on the Context
// to be used later in other endpoints. // to be used later in other endpoints.
func ListQuery(obj interface{}) func(http.Handler) http.Handler { func ListQuery(obj any) func(http.Handler) http.Handler {
schemaData := tags.GetFilterSchema(obj) schemaData := tags.GetFilterSchema(obj)
filterMap := tags.GetFilterMap(obj, "") filterMap := tags.GetFilterMap(obj, "")
@@ -29,13 +29,13 @@ func ListQuery(obj interface{}) func(http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() ctx := r.Context()
ctx, statusCode, errMsg, errors := listQueryFilters(r, ctx, schemaData) ctx, statusCode, errMsg, errors := listQueryFilters(ctx, r, schemaData)
if statusCode > 0 { if statusCode > 0 {
h.ResultErrorJSON(w, r, statusCode, errMsg, errors) h.ResultErrorJSON(w, r, statusCode, errMsg, errors)
return return
} }
ctx, statusCode, errMsg = listQuerySort(r, filterMap, ctx) ctx, statusCode, errMsg = listQuerySort(ctx, r, filterMap)
if statusCode > 0 { if statusCode > 0 {
h.ResultErrorJSON(w, r, statusCode, errMsg, nil) h.ResultErrorJSON(w, r, statusCode, errMsg, nil)
return return
@@ -47,9 +47,9 @@ func ListQuery(obj interface{}) func(http.Handler) http.Handler {
} }
func listQuerySort( func listQuerySort(
ctx context.Context,
r *http.Request, r *http.Request,
filterMap map[string]model.FilterMapValue, filterMap map[string]model.FilterMapValue,
ctx context.Context,
) (context.Context, int, string) { ) (context.Context, int, string) {
var sortFields []model.Sort var sortFields []model.Sort
@@ -99,10 +99,10 @@ func listQuerySort(
} }
func listQueryFilters( func listQueryFilters(
r *http.Request,
ctx context.Context, ctx context.Context,
r *http.Request,
schemaData string, schemaData string,
) (context.Context, int, string, interface{}) { ) (context.Context, int, string, any) {
reservedFilterKeys := []string{ reservedFilterKeys := []string{
"limit", "limit",
"offset", "offset",

View File

@@ -53,7 +53,7 @@ func TestListQuery(t *testing.T) {
ctx = context.WithValue(ctx, c.FiltersCtxKey, tags.GetFilterSchema(testObj)) ctx = context.WithValue(ctx, c.FiltersCtxKey, tags.GetFilterSchema(testObj))
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
handler := middleware.ListQuery(testObj)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := middleware.ListQuery(testObj)(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
})) }))

View File

@@ -33,7 +33,6 @@ func CheckRequestSchema(ctx context.Context, schemaData string, payload []byte)
func EnforceRequestSchema(schemaData string) func(http.Handler) http.Handler { func EnforceRequestSchema(schemaData string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get content from context // Get content from context
bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte) bodyBytes, _ := r.Context().Value(c.BodyCtxKey).([]byte)

View File

@@ -29,7 +29,7 @@ import (
// NewRouter returns a new router object // NewRouter returns a new router object
func NewRouter() http.Handler { func NewRouter() http.Handler {
// Cors // Cors
cors := cors.New(cors.Options{ corss := cors.New(cors.Options{
AllowedOrigins: []string{"*"}, AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-Requested-With"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-Requested-With"},
@@ -42,7 +42,7 @@ func NewRouter() http.Handler {
middleware.AccessControl, middleware.AccessControl,
middleware.Cors(r), middleware.Cors(r),
middleware.Options(r), middleware.Options(r),
cors.Handler, corss.Handler,
chiMiddleware.RealIP, chiMiddleware.RealIP,
chiMiddleware.Recoverer, chiMiddleware.Recoverer,
chiMiddleware.Throttle(5), chiMiddleware.Throttle(5),

View File

@@ -18,7 +18,7 @@ func CreateDNSProvider() string {
allSchemasWrapped := make([]string, 0) allSchemasWrapped := make([]string, 0)
for providerName, provider := range allProviders { for providerName, provider := range allProviders {
schema, err := provider.GetJsonSchema() schema, err := provider.GetJSONSchema()
if err != nil { if err != nil {
logger.Error("ProviderSchemaError", eris.Wrapf(err, "Invalid Provider Schema for %s: %v", provider.Title, err)) logger.Error("ProviderSchemaError", eris.Wrapf(err, "Invalid Provider Schema for %s: %v", provider.Title, err))
} else { } else {

View File

@@ -3,9 +3,10 @@ package schema
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"npm/internal/entity/certificate"
"testing" "testing"
"npm/internal/entity/certificate"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@@ -1,6 +1,6 @@
package schema package schema
// UpdateHostTemplate is the schema for incoming data validation // UpdateNginxTemplate is the schema for incoming data validation
func UpdateNginxTemplate() string { func UpdateNginxTemplate() string {
return ` return `
{ {

View File

@@ -23,6 +23,7 @@ func InitArgs(version, commit *string) {
if appArguments.Version { if appArguments.Version {
fmt.Printf("v%s (%s)\n", *version, *commit) fmt.Printf("v%s (%s)\n", *version, *commit)
// nolint: revive
os.Exit(0) os.Exit(0)
} }
} }

View File

@@ -2,6 +2,7 @@ package config
import ( import (
"fmt" "fmt"
"npm/internal/logger" "npm/internal/logger"
) )

View File

@@ -46,8 +46,8 @@ func SetDB(db *gorm.DB) {
func connect() (*gorm.DB, error) { func connect() (*gorm.DB, error) {
var d gorm.Dialector var d gorm.Dialector
dsn := config.Configuration.DB.GetGormConnectURL() dsn := config.Configuration.DB.GetGormConnectURL()
switch strings.ToLower(config.Configuration.DB.Driver) {
switch strings.ToLower(config.Configuration.DB.Driver) {
case config.DatabaseSqlite: case config.DatabaseSqlite:
// autocreate(dsn) // autocreate(dsn)
d = sqlite.Open(dsn) d = sqlite.Open(dsn)

View File

@@ -2,8 +2,9 @@ package database
import ( import (
"fmt" "fmt"
"npm/internal/config"
"strings" "strings"
"npm/internal/config"
) )
const ( const (

View File

@@ -9,6 +9,8 @@ import (
"npm/internal/logger" "npm/internal/logger"
"github.com/amacneil/dbmate/v2/pkg/dbmate" "github.com/amacneil/dbmate/v2/pkg/dbmate"
// Drivers:
_ "github.com/amacneil/dbmate/v2/pkg/driver/mysql" _ "github.com/amacneil/dbmate/v2/pkg/driver/mysql"
_ "github.com/amacneil/dbmate/v2/pkg/driver/postgres" _ "github.com/amacneil/dbmate/v2/pkg/driver/postgres"
_ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite" _ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite"

View File

@@ -2,6 +2,7 @@ package dnsproviders
import ( import (
"encoding/json" "encoding/json"
"npm/internal/errors" "npm/internal/errors"
) )
@@ -31,8 +32,8 @@ type Provider struct {
Properties map[string]providerField `json:"properties"` Properties map[string]providerField `json:"properties"`
} }
// GetJsonSchema encodes this object as JSON string // GetJSONSchema encodes this object as JSON string
func (p *Provider) GetJsonSchema() (string, error) { func (p *Provider) GetJSONSchema() (string, error) {
b, err := json.Marshal(p) b, err := json.Marshal(p)
return string(b), err return string(b), err
} }

View File

@@ -1,9 +1,10 @@
package dnsproviders package dnsproviders
import ( import (
"npm/internal/util"
"testing" "testing"
"npm/internal/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/goleak" "go.uber.org/goleak"
) )
@@ -13,7 +14,7 @@ func TestAcmeDNSProvider(t *testing.T) {
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
provider := getDNSAcmeDNS() provider := getDNSAcmeDNS()
json, err := provider.GetJsonSchema() json, err := provider.GetJSONSchema()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, `{ assert.Equal(t, `{
"title": "dns_acmedns", "title": "dns_acmedns",

View File

@@ -1,9 +1,10 @@
package dnsproviders package dnsproviders
import ( import (
"npm/internal/util"
"testing" "testing"
"npm/internal/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/goleak" "go.uber.org/goleak"
) )
@@ -14,7 +15,7 @@ func TestAdProvider(t *testing.T) {
provider := getDNSAd() provider := getDNSAd()
provider.ConvertToUpdatable() provider.ConvertToUpdatable()
json, err := provider.GetJsonSchema() json, err := provider.GetJSONSchema()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, `{ assert.Equal(t, `{
"title": "dns_ad", "title": "dns_ad",

View File

@@ -1,9 +1,10 @@
package dnsproviders package dnsproviders
import ( import (
"npm/internal/util"
"testing" "testing"
"npm/internal/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/goleak" "go.uber.org/goleak"
) )
@@ -13,7 +14,7 @@ func TestAliProvider(t *testing.T) {
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
provider := getDNSAli() provider := getDNSAli()
json, err := provider.GetJsonSchema() json, err := provider.GetJSONSchema()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, `{ assert.Equal(t, `{
"title": "dns_ali", "title": "dns_ali",

View File

@@ -11,7 +11,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
Meta types.JSONB `json:"meta" gorm:"column:meta"` Meta types.JSONB `json:"meta" gorm:"column:meta"`

View File

@@ -139,13 +139,11 @@ func (s *testsuite) TestSave() {
func (s *testsuite) TestSetPassword() { func (s *testsuite) TestSetPassword() {
// goleak is used to detect goroutine leaks // goleak is used to detect goroutine leaks
defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
m := Model{UserID: 100} m := Model{UserID: 100}
err := m.SetPassword("abc123") err := m.SetPassword("abc123")
require.NoError(s.T(), err) require.NoError(s.T(), err)
assert.Equal(s.T(), TypeLocal, m.Type) assert.Equal(s.T(), TypeLocal, m.Type)
assert.Greater(s.T(), len(m.Secret), 15) assert.Greater(s.T(), len(m.Secret), 15)
} }
func (s *testsuite) TestValidateSecret() { func (s *testsuite) TestValidateSecret() {

View File

@@ -22,7 +22,7 @@ func GetByUserIDType(userID uint, authType string) (Model, error) {
return auth, result.Error return auth, result.Error
} }
// GetByUserIDType finds a user by id and type // GetByIdenityType finds a user by identity and type
func GetByIdenityType(identity string, authType string) (Model, error) { func GetByIdenityType(identity string, authType string) (Model, error) {
var auth Model var auth Model
db := database.GetDB() db := database.GetDB()

View File

@@ -17,7 +17,7 @@ const (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id"` UserID uint `json:"user_id" gorm:"column:user_id"`
Type string `json:"type" gorm:"column:type;default:local"` Type string `json:"type" gorm:"column:type;default:local"`
Identity string `json:"identity,omitempty" gorm:"column:identity"` Identity string `json:"identity,omitempty" gorm:"column:identity"`

View File

@@ -34,7 +34,7 @@ func OAuthCacheInit() {
type OAuthUser struct { type OAuthUser struct {
Identifier string `json:"identifier"` Identifier string `json:"identifier"`
Token string `json:"token"` Token string `json:"token"`
Resource map[string]interface{} `json:"resource"` Resource map[string]any `json:"resource"`
} }
// GetResourceField will attempt to get a field from the resource // GetResourceField will attempt to get a field from the resource

View File

@@ -105,7 +105,7 @@ func TestGetEmail(t *testing.T) {
{ {
name: "Email in resource", name: "Email in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"email": "user@example.com", "email": "user@example.com",
}, },
}, },
@@ -128,7 +128,7 @@ func TestGetEmail(t *testing.T) {
{ {
name: "No email or identifier", name: "No email or identifier",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{}, Resource: map[string]any{},
}, },
expected: "", expected: "",
}, },
@@ -151,7 +151,7 @@ func TestGetName(t *testing.T) {
{ {
name: "Nickname in resource", name: "Nickname in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"nickname": "user_nick", "nickname": "user_nick",
}, },
}, },
@@ -160,7 +160,7 @@ func TestGetName(t *testing.T) {
{ {
name: "Given name in resource", name: "Given name in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"given_name": "User Given", "given_name": "User Given",
}, },
}, },
@@ -169,7 +169,7 @@ func TestGetName(t *testing.T) {
{ {
name: "Name in resource", name: "Name in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"name": "User Name", "name": "User Name",
}, },
}, },
@@ -178,7 +178,7 @@ func TestGetName(t *testing.T) {
{ {
name: "Preferred username in resource", name: "Preferred username in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"preferred_username": "preferred_user", "preferred_username": "preferred_user",
}, },
}, },
@@ -187,7 +187,7 @@ func TestGetName(t *testing.T) {
{ {
name: "Username in resource", name: "Username in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"username": "user123", "username": "user123",
}, },
}, },
@@ -197,14 +197,14 @@ func TestGetName(t *testing.T) {
name: "No name fields in resource, fallback to identifier", name: "No name fields in resource, fallback to identifier",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Identifier: "fallback_identifier", Identifier: "fallback_identifier",
Resource: map[string]interface{}{}, Resource: map[string]any{},
}, },
expected: "fallback_identifier", expected: "fallback_identifier",
}, },
{ {
name: "No name fields and no identifier", name: "No name fields and no identifier",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{}, Resource: map[string]any{},
}, },
expected: "", expected: "",
}, },
@@ -212,7 +212,7 @@ func TestGetName(t *testing.T) {
name: "All fields", name: "All fields",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Identifier: "fallback_identifier", Identifier: "fallback_identifier",
Resource: map[string]interface{}{ Resource: map[string]any{
"nickname": "user_nick", "nickname": "user_nick",
"given_name": "User Given", "given_name": "User Given",
"name": "User Name", "name": "User Name",
@@ -248,7 +248,7 @@ func TestGetID(t *testing.T) {
{ {
name: "UID in resource", name: "UID in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"uid": "uid123", "uid": "uid123",
}, },
}, },
@@ -257,7 +257,7 @@ func TestGetID(t *testing.T) {
{ {
name: "User ID in resource", name: "User ID in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"user_id": "user_id123", "user_id": "user_id123",
}, },
}, },
@@ -266,7 +266,7 @@ func TestGetID(t *testing.T) {
{ {
name: "Username in resource", name: "Username in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"username": "username123", "username": "username123",
}, },
}, },
@@ -275,7 +275,7 @@ func TestGetID(t *testing.T) {
{ {
name: "Preferred username in resource", name: "Preferred username in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"preferred_username": "preferred_user", "preferred_username": "preferred_user",
}, },
}, },
@@ -284,7 +284,7 @@ func TestGetID(t *testing.T) {
{ {
name: "Email in resource", name: "Email in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"email": "user@example.com", "email": "user@example.com",
}, },
}, },
@@ -293,7 +293,7 @@ func TestGetID(t *testing.T) {
{ {
name: "Mail in resource", name: "Mail in resource",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{ Resource: map[string]any{
"mail": "mail@example.com", "mail": "mail@example.com",
}, },
}, },
@@ -302,7 +302,7 @@ func TestGetID(t *testing.T) {
{ {
name: "No identifier or resource fields", name: "No identifier or resource fields",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Resource: map[string]interface{}{}, Resource: map[string]any{},
}, },
expected: "", expected: "",
}, },
@@ -310,7 +310,7 @@ func TestGetID(t *testing.T) {
name: "All fields", name: "All fields",
oauthUser: OAuthUser{ oauthUser: OAuthUser{
Identifier: "user123", Identifier: "user123",
Resource: map[string]interface{}{ Resource: map[string]any{
"uid": "uid123", "uid": "uid123",
"user_id": "user_id123", "user_id": "user_id123",
"username": "username123", "username": "username123",

View File

@@ -44,7 +44,7 @@ const (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Type string `json:"type" gorm:"column:type" filter:"type,string"` Type string `json:"type" gorm:"column:type" filter:"type,string"`
CertificateAuthorityID types.NullableDBUint `json:"certificate_authority_id" gorm:"column:certificate_authority_id" filter:"certificate_authority_id,integer"` CertificateAuthorityID types.NullableDBUint `json:"certificate_authority_id" gorm:"column:certificate_authority_id" filter:"certificate_authority_id,integer"`

View File

@@ -210,7 +210,7 @@ func (s *testsuite) TestDelete() {
assert.Equal(s.T(), "Unable to delete a new object", err.Error()) assert.Equal(s.T(), "Unable to delete a new object", err.Error())
m2 := Model{ m2 := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
} }

View File

@@ -13,7 +13,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
AcmeshServer string `json:"acmesh_server" gorm:"column:acmesh_server" filter:"acmesh_server,string"` AcmeshServer string `json:"acmesh_server" gorm:"column:acmesh_server" filter:"acmesh_server,string"`
CABundle string `json:"ca_bundle" gorm:"column:ca_bundle" filter:"ca_bundle,string"` CABundle string `json:"ca_bundle" gorm:"column:ca_bundle" filter:"ca_bundle,string"`

View File

@@ -296,7 +296,7 @@ func (s *testsuite) TestDelete() {
assert.Equal(s.T(), "Unable to delete a new object", err.Error()) assert.Equal(s.T(), "Unable to delete a new object", err.Error())
m2 := Model{ m2 := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
} }

View File

@@ -14,7 +14,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
AcmeshName string `json:"acmesh_name" gorm:"column:acmesh_name" filter:"acmesh_name,string"` AcmeshName string `json:"acmesh_name" gorm:"column:acmesh_name" filter:"acmesh_name,string"`
@@ -70,8 +70,8 @@ func (m *Model) GetAcmeShEnvVars() ([]string, error) {
return envs, nil return envs, nil
} }
func getEnvsFromMeta(meta interface{}) []string { func getEnvsFromMeta(meta any) []string {
if rec, ok := meta.(map[string]interface{}); ok { if rec, ok := meta.(map[string]any); ok {
envs := make([]string, 0) envs := make([]string, 0)
for key, val := range rec { for key, val := range rec {
if f, ok := val.(string); ok { if f, ok := val.(string); ok {
@@ -81,8 +81,8 @@ func getEnvsFromMeta(meta interface{}) []string {
} }
} }
return envs return envs
} else { }
logger.Debug("getEnvsFromMeta: meta is not an map of strings") logger.Debug("getEnvsFromMeta: meta is not an map of strings")
return nil return nil
} }
}

View File

@@ -6,12 +6,13 @@ import (
) )
// GetFilterMap returns the filter map // GetFilterMap returns the filter map
func GetFilterMap(m interface{}, includeBaseEntity bool) map[string]model.FilterMapValue { // _ was called `includeBaseEntity`
func GetFilterMap(m any, _ bool) map[string]model.FilterMapValue {
filterMap := tags.GetFilterMap(m, "") filterMap := tags.GetFilterMap(m, "")
// TODO: this is done in GetFilterMap isn't it? // TODO: this is done in GetFilterMap isn't it?
// if includeBaseEntity { // if includeBaseEntity {
// return mergeFilterMaps(tags.GetFilterMap(model.ModelBase{}, ""), filterMap) // return mergeFilterMaps(tags.GetFilterMap(model.Base{}, ""), filterMap)
// } // }
return filterMap return filterMap

View File

@@ -189,7 +189,7 @@ func (s *testsuite) TestDelete() {
assert.Equal(s.T(), "Unable to delete a new object", err.Error()) assert.Equal(s.T(), "Unable to delete a new object", err.Error())
m2 := Model{ m2 := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
} }
@@ -203,7 +203,7 @@ func (s *testsuite) TestGetTemplate() {
defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
m := Model{ m := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
CreatedAt: time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC).UnixMilli(), CreatedAt: time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
UpdatedAt: time.Date(2018, 8, 12, 7, 30, 24, 16, time.UTC).UnixMilli(), UpdatedAt: time.Date(2018, 8, 12, 7, 30, 24, 16, time.UTC).UnixMilli(),

View File

@@ -27,7 +27,7 @@ const (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Type string `json:"type" gorm:"column:type" filter:"type,string"` Type string `json:"type" gorm:"column:type" filter:"type,string"`
NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"` NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"`

View File

@@ -14,12 +14,12 @@ type ListResponse struct {
Limit int `json:"limit"` Limit int `json:"limit"`
Sort []model.Sort `json:"sort"` Sort []model.Sort `json:"sort"`
Filter []model.Filter `json:"filter,omitempty"` Filter []model.Filter `json:"filter,omitempty"`
Items interface{} `json:"items,omitempty"` Items any `json:"items,omitempty"`
} }
// ListQueryBuilder is used to setup queries for lists // ListQueryBuilder is used to setup queries for lists
func ListQueryBuilder( func ListQueryBuilder(
pageInfo *model.PageInfo, _ *model.PageInfo,
filters []model.Filter, filters []model.Filter,
filterMap map[string]model.FilterMapValue, filterMap map[string]model.FilterMapValue,
) *gorm.DB { ) *gorm.DB {

View File

@@ -9,7 +9,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
Type string `json:"type" gorm:"column:type" filter:"type,string"` Type string `json:"type" gorm:"column:type" filter:"type,string"`

View File

@@ -10,6 +10,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
// ScopeOffsetLimit ...
func ScopeOffsetLimit(pageInfo *model.PageInfo) func(db *gorm.DB) *gorm.DB { func ScopeOffsetLimit(pageInfo *model.PageInfo) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB {
if pageInfo.Offset > 0 || pageInfo.Limit > 0 { if pageInfo.Offset > 0 || pageInfo.Limit > 0 {
@@ -19,6 +20,7 @@ func ScopeOffsetLimit(pageInfo *model.PageInfo) func(db *gorm.DB) *gorm.DB {
} }
} }
// ScopeOrderBy ...
func ScopeOrderBy(sort []model.Sort, defaultSort model.Sort) func(db *gorm.DB) *gorm.DB { func ScopeOrderBy(sort []model.Sort, defaultSort model.Sort) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB {
if sort != nil { if sort != nil {
@@ -36,6 +38,7 @@ func ScopeOrderBy(sort []model.Sort, defaultSort model.Sort) func(db *gorm.DB) *
} }
} }
// ScopeFilters ...
func ScopeFilters(filters []model.Filter, filterMap map[string]model.FilterMapValue) func(db *gorm.DB) *gorm.DB { func ScopeFilters(filters []model.Filter, filterMap map[string]model.FilterMapValue) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB {
like := database.GetCaseInsensitiveLike() like := database.GetCaseInsensitiveLike()

View File

@@ -11,7 +11,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
Description string `json:"description" gorm:"column:description" filter:"description,string"` Description string `json:"description" gorm:"column:description" filter:"description,string"`
Value datatypes.JSON `json:"value" gorm:"column:value"` Value datatypes.JSON `json:"value" gorm:"column:value"`

View File

@@ -10,7 +10,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
ExpiresOn types.DBDate `json:"expires_on" gorm:"column:expires_on" filter:"expires_on,integer"` ExpiresOn types.DBDate `json:"expires_on" gorm:"column:expires_on" filter:"expires_on,integer"`
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Provider string `json:"provider" gorm:"column:provider" filter:"provider,string"` Provider string `json:"provider" gorm:"column:provider" filter:"provider,string"`

View File

@@ -17,7 +17,7 @@ import (
// Model is the model // Model is the model
// See: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream // See: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
type Model struct { type Model struct {
model.ModelBase model.Base
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"` UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"` NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"`

View File

@@ -7,7 +7,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
UpstreamID uint `json:"upstream_id" gorm:"column:upstream_id" filter:"upstream_id,integer"` UpstreamID uint `json:"upstream_id" gorm:"column:upstream_id" filter:"upstream_id,integer"`
Server string `json:"server" gorm:"column:server" filter:"server,string"` Server string `json:"server" gorm:"column:server" filter:"server,string"`
Weight int `json:"weight" gorm:"column:weight" filter:"weight,integer"` Weight int `json:"weight" gorm:"column:weight" filter:"weight,integer"`

View File

@@ -226,7 +226,7 @@ func (s *testsuite) TestDelete() {
assert.Equal(s.T(), "Unable to delete a new object", err.Error()) assert.Equal(s.T(), "Unable to delete a new object", err.Error())
m2 := Model{ m2 := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
Name: "John Doe", Name: "John Doe",
@@ -254,6 +254,10 @@ func (s *testsuite) TestDeleteAll() {
WithArgs(false). WithArgs(false).
WillReturnResult(sqlmock.NewResult(0, 1)) WillReturnResult(sqlmock.NewResult(0, 1))
s.mock.
ExpectExec(regexp.QuoteMeta(`DELETE FROM "auth"`)).
WillReturnResult(sqlmock.NewResult(0, 1))
err := DeleteAll() err := DeleteAll()
require.NoError(s.T(), err) require.NoError(s.T(), err)
require.NoError(s.T(), s.mock.ExpectationsWereMet()) require.NoError(s.T(), s.mock.ExpectationsWereMet())
@@ -438,7 +442,7 @@ func (s *testsuite) TestSaveCapabilitiesInvalid() {
// Empty model returns error // Empty model returns error
m := Model{ m := Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
Capabilities: []string{"doesnotexist", "hosts.manage"}, Capabilities: []string{"doesnotexist", "hosts.manage"},

View File

@@ -89,14 +89,26 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (ent
// DeleteAll will do just that, and should only be used for testing purposes. // DeleteAll will do just that, and should only be used for testing purposes.
func DeleteAll() error { func DeleteAll() error {
db := database.GetDB() db := database.GetDB()
result := db.Exec(fmt.Sprintf(`DELETE FROM %s WHERE is_system = ?`, database.QuoteTableName("user")), false) if result := db.Exec(
fmt.Sprintf(`DELETE FROM %s WHERE is_system = ?`, database.QuoteTableName("user")),
false,
); result.Error != nil {
return result.Error return result.Error
} }
if result := db.Exec(
fmt.Sprintf(`DELETE FROM %s`, database.QuoteTableName("auth")),
); result.Error != nil {
return result.Error
}
return nil
}
// GetCapabilities gets capabilities for a user // GetCapabilities gets capabilities for a user
func GetCapabilities(userID uint) ([]string, error) { func GetCapabilities(userID uint) ([]string, error) {
capabilities := make([]string, 0) capabilities := make([]string, 0)
var hasCapabilities []UserHasCapabilityModel var hasCapabilities []HasCapabilityModel
db := database.GetDB() db := database.GetDB()
if result := db.Where("user_id = ?", userID).Find(&hasCapabilities); result.Error != nil { if result := db.Where("user_id = ?", userID).Find(&hasCapabilities); result.Error != nil {
return nil, result.Error return nil, result.Error

View File

@@ -16,7 +16,7 @@ import (
// Model is the model // Model is the model
type Model struct { type Model struct {
model.ModelBase model.Base
Name string `json:"name" gorm:"column:name" filter:"name,string"` Name string `json:"name" gorm:"column:name" filter:"name,string"`
Email string `json:"email" gorm:"column:email" filter:"email,email"` Email string `json:"email" gorm:"column:email" filter:"email,email"`
IsDisabled bool `json:"is_disabled" gorm:"column:is_disabled" filter:"is_disabled,boolean"` IsDisabled bool `json:"is_disabled" gorm:"column:is_disabled" filter:"is_disabled,boolean"`
@@ -33,14 +33,14 @@ func (Model) TableName() string {
return "user" return "user"
} }
// UserHasCapabilityModel is the model // HasCapabilityModel is the model
type UserHasCapabilityModel struct { type HasCapabilityModel struct {
UserID uint `json:"user_id" gorm:"column:user_id"` UserID uint `json:"user_id" gorm:"column:user_id"`
CapabilityName string `json:"name" gorm:"column:capability_name"` CapabilityName string `json:"name" gorm:"column:capability_name"`
} }
// TableName overrides the table name used by gorm // TableName overrides the table name used by gorm
func (UserHasCapabilityModel) TableName() string { func (HasCapabilityModel) TableName() string {
return "user_has_capability" return "user_has_capability"
} }
@@ -99,15 +99,15 @@ func (m *Model) SetPermissions(permissions []string) error {
db := database.GetDB() db := database.GetDB()
// Wipe out previous permissions // Wipe out previous permissions
if result := db.Where("user_id = ?", m.ID).Delete(&UserHasCapabilityModel{}); result.Error != nil { if result := db.Where("user_id = ?", m.ID).Delete(&HasCapabilityModel{}); result.Error != nil {
return result.Error return result.Error
} }
if len(permissions) > 0 { if len(permissions) > 0 {
// Add new permissions // Add new permissions
objs := []*UserHasCapabilityModel{} objs := []*HasCapabilityModel{}
for _, permission := range permissions { for _, permission := range permissions {
objs = append(objs, &UserHasCapabilityModel{UserID: m.ID, CapabilityName: permission}) objs = append(objs, &HasCapabilityModel{UserID: m.ID, CapabilityName: permission})
} }
if result := db.Create(objs); result.Error != nil { if result := db.Create(objs); result.Error != nil {
return result.Error return result.Error

View File

@@ -2,6 +2,7 @@ package jobqueue
import ( import (
"fmt" "fmt"
"npm/internal/logger" "npm/internal/logger"
) )

View File

@@ -9,7 +9,7 @@ var currentKeys KeysModel
// KeysModel is the model // KeysModel is the model
type KeysModel struct { type KeysModel struct {
model.ModelBase model.Base
PublicKey string `gorm:"column:public_key"` PublicKey string `gorm:"column:public_key"`
PrivateKey string `gorm:"column:private_key"` PrivateKey string `gorm:"column:private_key"`
} }
@@ -19,7 +19,7 @@ func (KeysModel) TableName() string {
return "jwt_keys" return "jwt_keys"
} }
// LoadByID will load from an ID // LoadLatest will load the latest keys
func (m *KeysModel) LoadLatest() error { func (m *KeysModel) LoadLatest() error {
db := database.GetDB() db := database.GetDB()
result := db.Order("created_at DESC").First(&m) result := db.Order("created_at DESC").First(&m)

View File

@@ -183,7 +183,7 @@ func (s *testsuite) TestGetPrivateKey() {
// Set currentKeys and try again // Set currentKeys and try again
currentKeys = KeysModel{ currentKeys = KeysModel{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
PrivateKey: s.privateKeyString, PrivateKey: s.privateKeyString,
@@ -210,7 +210,7 @@ func (s *testsuite) TestGetPublicKey() {
// Set currentKeys and try again // Set currentKeys and try again
currentKeys = KeysModel{ currentKeys = KeysModel{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
PrivateKey: s.privateKeyString, PrivateKey: s.privateKeyString,
@@ -228,7 +228,7 @@ func (s *testsuite) TestGenerate() {
defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(s.T(), goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
currentKeys = KeysModel{ currentKeys = KeysModel{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
PrivateKey: s.privateKeyString, PrivateKey: s.privateKeyString,
@@ -236,7 +236,7 @@ func (s *testsuite) TestGenerate() {
} }
usr := user.Model{ usr := user.Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
} }

View File

@@ -24,11 +24,11 @@ type Config struct {
// Interface for a logger // Interface for a logger
type Interface interface { type Interface interface {
GetLogLevel() Level GetLogLevel() Level
Debug(format string, args ...interface{}) Debug(format string, args ...any)
Info(format string, args ...interface{}) Info(format string, args ...any)
Warn(format string, args ...interface{}) Warn(format string, args ...any)
Error(errorClass string, err error, args ...interface{}) Error(errorClass string, err error, args ...any)
Errorf(errorClass, format string, err error, args ...interface{}) Errorf(errorClass, format string, err error, args ...any)
} }
// ConfigurableLogger is an interface for a logger that can be configured // ConfigurableLogger is an interface for a logger that can be configured

View File

@@ -71,17 +71,17 @@ func GetLogLevel() Level {
} }
// Debug logs if the log level is set to DebugLevel or below. Arguments are handled in the manner of fmt.Printf. // Debug logs if the log level is set to DebugLevel or below. Arguments are handled in the manner of fmt.Printf.
func Debug(format string, args ...interface{}) { func Debug(format string, args ...any) {
logger.Debug(format, args...) logger.Debug(format, args...)
} }
// Info logs if the log level is set to InfoLevel or below. Arguments are handled in the manner of fmt.Printf. // Info logs if the log level is set to InfoLevel or below. Arguments are handled in the manner of fmt.Printf.
func Info(format string, args ...interface{}) { func Info(format string, args ...any) {
logger.Info(format, args...) logger.Info(format, args...)
} }
// Warn logs if the log level is set to WarnLevel or below. Arguments are handled in the manner of fmt.Printf. // Warn logs if the log level is set to WarnLevel or below. Arguments are handled in the manner of fmt.Printf.
func Warn(format string, args ...interface{}) { func Warn(format string, args ...any) {
logger.Warn(format, args...) logger.Warn(format, args...)
} }
@@ -134,7 +134,7 @@ var logLevels = map[Level]string{
ErrorLevel: "ERROR", ErrorLevel: "ERROR",
} }
func (l *Logger) logLevel(logLevel Level, format string, args ...interface{}) { func (l *Logger) logLevel(logLevel Level, format string, args ...any) {
if logLevel < l.LogThreshold { if logLevel < l.LogThreshold {
return return
} }
@@ -146,7 +146,7 @@ func (l *Logger) logLevel(logLevel Level, format string, args ...interface{}) {
if len(args) > 1 { if len(args) > 1 {
args = args[1:] args = args[1:]
} else { } else {
args = []interface{}{} args = []any{}
} }
} }
@@ -202,17 +202,17 @@ func (l *Logger) GetLogLevel() Level {
} }
// Debug logs if the log level is set to DebugLevel or below. Arguments are handled in the manner of fmt.Printf. // Debug logs if the log level is set to DebugLevel or below. Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Debug(format string, args ...interface{}) { func (l *Logger) Debug(format string, args ...any) {
l.logLevel(DebugLevel, format, args...) l.logLevel(DebugLevel, format, args...)
} }
// Info logs if the log level is set to InfoLevel or below. Arguments are handled in the manner of fmt.Printf. // Info logs if the log level is set to InfoLevel or below. Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Info(format string, args ...interface{}) { func (l *Logger) Info(format string, args ...any) {
l.logLevel(InfoLevel, format, args...) l.logLevel(InfoLevel, format, args...)
} }
// Warn logs if the log level is set to WarnLevel or below. Arguments are handled in the manner of fmt.Printf. // Warn logs if the log level is set to WarnLevel or below. Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Warn(format string, args ...interface{}) { func (l *Logger) Warn(format string, args ...any) {
l.logLevel(WarnLevel, format, args...) l.logLevel(WarnLevel, format, args...)
} }

View File

@@ -4,8 +4,8 @@ import (
"gorm.io/plugin/soft_delete" "gorm.io/plugin/soft_delete"
) )
// ModelBase include common fields for db control // Base include common fields for db control
type ModelBase struct { type Base struct {
ID uint `json:"id" gorm:"column:id;primaryKey" filter:"id,integer"` ID uint `json:"id" gorm:"column:id;primaryKey" filter:"id,integer"`
CreatedAt int64 `json:"created_at" gorm:"<-:create;autoCreateTime:milli;column:created_at" filter:"created_at,date"` CreatedAt int64 `json:"created_at" gorm:"<-:create;autoCreateTime:milli;column:created_at" filter:"created_at,date"`
UpdatedAt int64 `json:"updated_at" gorm:"<-;autoUpdateTime:milli;column:updated_at" filter:"updated_at,date"` UpdatedAt int64 `json:"updated_at" gorm:"<-;autoUpdateTime:milli;column:updated_at" filter:"updated_at,date"`

View File

@@ -151,14 +151,14 @@ func ConfigureUpstream(u upstream.Model) error {
return u.Save(true) return u.Save(true)
} }
func getHostFilename(h host.Model, append string) string { func getHostFilename(h host.Model, appends string) string {
confDir := fmt.Sprintf("%s/nginx/hosts", config.Configuration.DataFolder) confDir := fmt.Sprintf("%s/nginx/hosts", config.Configuration.DataFolder)
return fmt.Sprintf("%s/host_%d.conf%s", confDir, h.ID, append) return fmt.Sprintf("%s/host_%d.conf%s", confDir, h.ID, appends)
} }
func getUpstreamFilename(u upstream.Model, append string) string { func getUpstreamFilename(u upstream.Model, appends string) string {
confDir := fmt.Sprintf("%s/nginx/upstreams", config.Configuration.DataFolder) confDir := fmt.Sprintf("%s/nginx/upstreams", config.Configuration.DataFolder)
return fmt.Sprintf("%s/upstream_%d.conf%s", confDir, u.ID, append) return fmt.Sprintf("%s/upstream_%d.conf%s", confDir, u.ID, appends)
} }
func removeHostFiles(h host.Model) { func removeHostFiles(h host.Model) {

View File

@@ -1,10 +1,11 @@
package nginx package nginx
import ( import (
"testing"
"npm/internal/entity/host" "npm/internal/entity/host"
"npm/internal/model" "npm/internal/model"
"npm/internal/test" "npm/internal/test"
"testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/goleak" "go.uber.org/goleak"
@@ -24,7 +25,7 @@ func TestGetHostFilename(t *testing.T) {
{ {
"test1", "test1",
host.Model{ host.Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
}, },
@@ -34,7 +35,7 @@ func TestGetHostFilename(t *testing.T) {
{ {
"test2", "test2",
host.Model{ host.Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 10, ID: 10,
}, },
}, },

View File

@@ -54,7 +54,7 @@ server {
IsDisabled: false, IsDisabled: false,
}, },
cert: certificate.Model{ cert: certificate.Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 77, ID: 77,
}, },
Status: certificate.StatusProvided, Status: certificate.StatusProvided,
@@ -79,7 +79,7 @@ server {
IsDisabled: false, IsDisabled: false,
}, },
cert: certificate.Model{ cert: certificate.Model{
ModelBase: model.ModelBase{ Base: model.Base{
ID: 66, ID: 66,
}, },
Status: certificate.StatusProvided, Status: certificate.StatusProvided,
@@ -108,18 +108,18 @@ server {
}, },
} }
for _, test := range tests { for _, tst := range tests {
t.Run(test.name, func(st *testing.T) { t.Run(tst.name, func(st *testing.T) {
templateData := TemplateData{ templateData := TemplateData{
ConfDir: "/etc/nginx/conf.d", ConfDir: "/etc/nginx/conf.d",
DataDir: "/data", DataDir: "/data",
Host: test.host.GetTemplate(), Host: tst.host.GetTemplate(),
Certificate: test.cert.GetTemplate(), Certificate: tst.cert.GetTemplate(),
} }
output, err := renderTemplate(template, templateData) output, err := renderTemplate(template, templateData)
assert.Equal(t, test.want.err, err) assert.Equal(st, tst.want.err, err)
assert.Equal(t, test.want.output, output) assert.Equal(st, tst.want.output, output)
}) })
} }
} }

View File

@@ -26,7 +26,7 @@ func Get() *sse.Server {
if instance == nil { if instance == nil {
instance = sse.NewServer(&sse.Options{ instance = sse.NewServer(&sse.Options{
Logger: logger.Get(), Logger: logger.Get(),
ChannelNameFunc: func(request *http.Request) string { ChannelNameFunc: func(_ *http.Request) string {
return defaultChannel // This is the channel for all updates regardless of visibility return defaultChannel // This is the channel for all updates regardless of visibility
}, },
}) })

View File

@@ -14,7 +14,8 @@ import (
"github.com/rotisserie/eris" "github.com/rotisserie/eris"
) )
func GetFilterMap(m interface{}, globalTablePrefix string) map[string]model.FilterMapValue { // GetFilterMap ...
func GetFilterMap(m any, globalTablePrefix string) map[string]model.FilterMapValue {
name := getName(m) name := getName(m)
filterMap := make(map[string]model.FilterMapValue) filterMap := make(map[string]model.FilterMapValue)
@@ -39,8 +40,8 @@ func GetFilterMap(m interface{}, globalTablePrefix string) map[string]model.Filt
// If this is an entity model (and it probably is) // If this is an entity model (and it probably is)
// then include the base model as well // then include the base model as well
if strings.Contains(name, ".Model") && !strings.Contains(name, "ModelBase") { if strings.Contains(name, ".Model") && !strings.Contains(name, "Base") {
filterMap = GetFilterMap(model.ModelBase{}, globalTablePrefix) filterMap = GetFilterMap(model.Base{}, globalTablePrefix)
} }
if t.Kind() != reflect.Struct { if t.Kind() != reflect.Struct {
@@ -128,7 +129,7 @@ func getFilterTagSchema(filterTag string) string {
// GetFilterSchema creates a jsonschema for validating filters, based on the model // GetFilterSchema creates a jsonschema for validating filters, based on the model
// object given and by reading the struct "filter" tags. // object given and by reading the struct "filter" tags.
func GetFilterSchema(m interface{}) string { func GetFilterSchema(m any) string {
filterMap := GetFilterMap(m, "") filterMap := GetFilterMap(m, "")
schemas := make([]string, 0) schemas := make([]string, 0)

View File

@@ -10,7 +10,7 @@ import (
var tagCache map[string]map[string]model.FilterMapValue var tagCache map[string]map[string]model.FilterMapValue
// getName returns the name of the type given // getName returns the name of the type given
func getName(m interface{}) string { func getName(m any) string {
fc := reflect.TypeOf(m) fc := reflect.TypeOf(m)
return fmt.Sprint(fc) return fmt.Sprint(fc)
} }

View File

@@ -12,6 +12,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
// Setup ...
func Setup() (sqlmock.Sqlmock, error) { func Setup() (sqlmock.Sqlmock, error) {
db, mock, err := sqlmock.New() db, mock, err := sqlmock.New()
if err != nil { if err != nil {
@@ -26,6 +27,7 @@ func Setup() (sqlmock.Sqlmock, error) {
return mock, err return mock, err
} }
// InitConfig ...
func InitConfig(t *testing.T, envs ...string) { func InitConfig(t *testing.T, envs ...string) {
if len(envs) > 0 { if len(envs) > 0 {
for _, env := range envs { for _, env := range envs {

View File

@@ -18,7 +18,7 @@ func (d DBDate) Value() (driver.Value, error) {
} }
// Scan takes data from the database and modifies it for Go Types // Scan takes data from the database and modifies it for Go Types
func (d *DBDate) Scan(src interface{}) error { func (d *DBDate) Scan(src any) error {
d.Time = time.Unix(src.(int64), 0) d.Time = time.Unix(src.(int64), 0)
return nil return nil
} }

View File

@@ -22,7 +22,7 @@ func (d NullableDBInt) Value() (driver.Value, error) {
} }
// Scan takes data from the database and modifies it for Go Types // Scan takes data from the database and modifies it for Go Types
func (d *NullableDBInt) Scan(src interface{}) error { func (d *NullableDBInt) Scan(src any) error {
var i int var i int
switch v := src.(type) { switch v := src.(type) {
case int: case int:

View File

@@ -18,16 +18,19 @@ func (d NullableDBUint) Value() (driver.Value, error) {
} }
// According to current database/sql docs, the sql has four builtin functions that // According to current database/sql docs, the sql has four builtin functions that
// returns driver.Value, and the underlying types are `int64`, `float64`, `string` and `bool` // returns driver.Value, and the underlying types are `int64`, `float64`, `string` and `bool`
// nolint: gosec
return driver.Value(int64(d.Uint)), nil return driver.Value(int64(d.Uint)), nil
} }
// Scan takes data from the database and modifies it for Go Types // Scan takes data from the database and modifies it for Go Types
func (d *NullableDBUint) Scan(src interface{}) error { func (d *NullableDBUint) Scan(src any) error {
var i uint var i uint
switch v := src.(type) { switch v := src.(type) {
case int: case int:
// nolint: gosec
i = uint(v) i = uint(v)
case int64: case int64:
// nolint: gosec
i = uint(v) i = uint(v)
case float32: case float32:
i = uint(v) i = uint(v)
@@ -35,6 +38,7 @@ func (d *NullableDBUint) Scan(src interface{}) error {
i = uint(v) i = uint(v)
case string: case string:
a, _ := strconv.Atoi(v) a, _ := strconv.Atoi(v)
// nolint: gosec
i = uint(a) i = uint(a)
} }
d.Uint = i d.Uint = i

View File

@@ -50,7 +50,7 @@ func TestNullableDBUint_Scan(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
input interface{} input any
wantUint uint wantUint uint
wantErr bool wantErr bool
}{ }{

View File

@@ -10,17 +10,17 @@ import (
// JSONB can be anything // JSONB can be anything
type JSONB struct { type JSONB struct {
Encoded string `json:"decoded"` Encoded string `json:"decoded"`
Decoded interface{} `json:"encoded"` Decoded any `json:"encoded"`
} }
// Value encodes the type ready for the database // Value encodes the type ready for the database
func (j JSONB) Value() (driver.Value, error) { func (j JSONB) Value() (driver.Value, error) {
json, err := json.Marshal(j.Decoded) jsn, err := json.Marshal(j.Decoded)
return driver.Value(string(json)), err return driver.Value(string(jsn)), err
} }
// Scan takes data from the database and modifies it for Go Types // Scan takes data from the database and modifies it for Go Types
func (j *JSONB) Scan(src interface{}) error { func (j *JSONB) Scan(src any) error {
var jsonb JSONB var jsonb JSONB
var srcString string var srcString string
switch v := src.(type) { switch v := src.(type) {

View File

@@ -8,7 +8,7 @@ import (
// TestJSONBValue tests the Value method of the JSONB type // TestJSONBValue tests the Value method of the JSONB type
func TestJSONBValue(t *testing.T) { func TestJSONBValue(t *testing.T) {
j := JSONB{ j := JSONB{
Decoded: map[string]interface{}{ Decoded: map[string]any{
"name": "John", "name": "John",
"age": 30, "age": 30,
}, },
@@ -35,7 +35,7 @@ func TestJSONBScan(t *testing.T) {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
expectedDecoded := map[string]interface{}{ expectedDecoded := map[string]any{
"name": "John", "name": "John",
"age": 30, "age": 30,
} }
@@ -59,7 +59,7 @@ func TestJSONBUnmarshalJSON(t *testing.T) {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
expectedDecoded := map[string]interface{}{ expectedDecoded := map[string]any{
"name": "John", "name": "John",
"age": 30, "age": 30,
} }
@@ -76,7 +76,7 @@ func TestJSONBUnmarshalJSON(t *testing.T) {
// TestJSONBMarshalJSON tests the MarshalJSON method of the JSONB type // TestJSONBMarshalJSON tests the MarshalJSON method of the JSONB type
func TestJSONBMarshalJSON(t *testing.T) { func TestJSONBMarshalJSON(t *testing.T) {
j := JSONB{ j := JSONB{
Decoded: map[string]interface{}{ Decoded: map[string]any{
"name": "John", "name": "John",
"age": 30, "age": 30,
}, },
@@ -113,7 +113,7 @@ func TestJSONBAsStringArray(t *testing.T) {
} }
// Helper function to compare JSON objects // Helper function to compare JSON objects
func jsonEqual(a, b interface{}) bool { func jsonEqual(a, b any) bool {
aJSON, _ := json.Marshal(a) aJSON, _ := json.Marshal(a)
bJSON, _ := json.Marshal(b) bJSON, _ := json.Marshal(b)
return string(aJSON) == string(bJSON) return string(aJSON) == string(bJSON)

View File

@@ -23,7 +23,7 @@ func (d NullableDBDate) Value() (driver.Value, error) {
} }
// Scan takes data from the database and modifies it for Go Types // Scan takes data from the database and modifies it for Go Types
func (d *NullableDBDate) Scan(src interface{}) error { func (d *NullableDBDate) Scan(src any) error {
var tme time.Time var tme time.Time
if src != nil { if src != nil {
tme = time.Unix(src.(int64), 0) tme = time.Unix(src.(int64), 0)

View File

@@ -1,9 +1,9 @@
package util package util
// FindItemInInterface Find key in interface (recursively) and return value as interface // FindItemInInterface Find key in interface (recursively) and return value as interface
func FindItemInInterface(key string, obj interface{}) (interface{}, bool) { func FindItemInInterface(key string, obj any) (any, bool) {
// if the argument is not a map, ignore it // if the argument is not a map, ignore it
mobj, ok := obj.(map[string]interface{}) mobj, ok := obj.(map[string]any)
if !ok { if !ok {
return nil, false return nil, false
} }
@@ -15,14 +15,14 @@ func FindItemInInterface(key string, obj interface{}) (interface{}, bool) {
} }
// if the value is a map, search recursively // if the value is a map, search recursively
if m, ok := v.(map[string]interface{}); ok { if m, ok := v.(map[string]any); ok {
if res, ok := FindItemInInterface(key, m); ok { if res, ok := FindItemInInterface(key, m); ok {
return res, true return res, true
} }
} }
// if the value is an array, search recursively // if the value is an array, search recursively
// from each element // from each element
if va, ok := v.([]interface{}); ok { if va, ok := v.([]any); ok {
for _, a := range va { for _, a := range va {
if res, ok := FindItemInInterface(key, a); ok { if res, ok := FindItemInInterface(key, a); ok {
return res, true return res, true

View File

@@ -11,13 +11,13 @@ func TestFindItemInInterface(t *testing.T) {
// goleak is used to detect goroutine leaks // goleak is used to detect goroutine leaks
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener")) defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
obj := map[string]interface{}{ obj := map[string]any{
"key1": "value1", "key1": "value1",
"key2": 10, "key2": 10,
"key3": map[string]interface{}{ "key3": map[string]any{
"nestedKey": "nestedValue", "nestedKey": "nestedValue",
}, },
"key4": []interface{}{"item1", "item2"}, "key4": []any{"item1", "item2"},
} }
// Test case 1: Key exists at the top level // Test case 1: Key exists at the top level

View File

@@ -1,7 +1,7 @@
package util package util
// MapContainsKey is fairly self explanatory // MapContainsKey is fairly self explanatory
func MapContainsKey(dict map[string]interface{}, key string) bool { func MapContainsKey(dict map[string]any, key string) bool {
if _, ok := dict[key]; ok { if _, ok := dict[key]; ok {
return true return true
} }

View File

@@ -19,7 +19,7 @@ func TestMapContainsKey(t *testing.T) {
var r rect var r rect
r.width = 5 r.width = 5
r.height = 5 r.height = 5
m := map[string]interface{}{ m := map[string]any{
"rect_width": r.width, "rect_width": r.width,
"rect_height": r.height, "rect_height": r.height,
} }

View File

@@ -35,8 +35,8 @@ func ConvertIntSliceToString(slice []int) string {
} }
// ConvertStringSliceToInterface is required in some special cases // ConvertStringSliceToInterface is required in some special cases
func ConvertStringSliceToInterface(slice []string) []interface{} { func ConvertStringSliceToInterface(slice []string) []any {
res := make([]interface{}, len(slice)) res := make([]any, len(slice))
for i := range slice { for i := range slice {
res[i] = slice[i] res[i] = slice[i]
} }

View File

@@ -99,11 +99,11 @@ func TestConvertIntSliceToString(t *testing.T) {
func TestConvertStringSliceToInterface(t *testing.T) { func TestConvertStringSliceToInterface(t *testing.T) {
testCases := []struct { testCases := []struct {
input []string input []string
expected []interface{} expected []any
}{ }{
{[]string{"hello", "world"}, []interface{}{"hello", "world"}}, {[]string{"hello", "world"}, []any{"hello", "world"}},
{[]string{"apple", "banana", "cherry"}, []interface{}{"apple", "banana", "cherry"}}, {[]string{"apple", "banana", "cherry"}, []any{"apple", "banana", "cherry"}},
{[]string{}, []interface{}{}}, // Empty slice should return an empty slice {[]string{}, []any{}}, // Empty slice should return an empty slice
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@@ -1,10 +1,11 @@
package validator package validator
import ( import (
"testing"
"npm/internal/entity/nginxtemplate" "npm/internal/entity/nginxtemplate"
"npm/internal/entity/upstream" "npm/internal/entity/upstream"
"npm/internal/entity/upstreamserver" "npm/internal/entity/upstreamserver"
"testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"

Binary file not shown.

View File

@@ -44,7 +44,7 @@ services:
- redis_vol:/data - redis_vol:/data
authentik: authentik:
image: ghcr.io/goauthentik/server:2024.8.3 image: ghcr.io/goauthentik/server:2024.10.1
restart: unless-stopped restart: unless-stopped
command: server command: server
env_file: env_file:
@@ -54,7 +54,7 @@ services:
- db-postgres - db-postgres
authentik-worker: authentik-worker:
image: ghcr.io/goauthentik/server:2024.8.3 image: ghcr.io/goauthentik/server:2024.10.1
restart: unless-stopped restart: unless-stopped
command: worker command: worker
env_file: env_file:
@@ -64,11 +64,11 @@ services:
- db-postgres - db-postgres
authentik-ldap: authentik-ldap:
image: ghcr.io/goauthentik/ldap image: ghcr.io/goauthentik/ldap:2024.10.1
environment: environment:
AUTHENTIK_HOST: 'http://authentik:9000' AUTHENTIK_HOST: 'http://authentik:9000'
AUTHENTIK_INSECURE: 'true' AUTHENTIK_INSECURE: 'true'
AUTHENTIK_TOKEN: '1N7z2r5PZrNBauuyDZSnlhU4gPSih7bkooIgqbvhzBbrA1MGYyDGZmBasJqU' AUTHENTIK_TOKEN: 'wKYZuRcI0ETtb8vWzMCr04oNbhrQUUICy89hSpDln1OEKLjiNEuQ51044Vkp'
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- authentik - authentik

View File

@@ -32,7 +32,7 @@ services:
- ca.internal - ca.internal
pdns: pdns:
image: pschiffe/pdns-mysql image: pschiffe/pdns-mysql:4.8
volumes: volumes:
- '/etc/localtime:/etc/localtime:ro' - '/etc/localtime:/etc/localtime:ro'
environment: environment:

View File

@@ -75,7 +75,7 @@ services:
- npm - npm
npm-pdns: npm-pdns:
image: pschiffe/pdns-mysql image: pschiffe/pdns-mysql:4.8
container_name: "npm.pdns" container_name: "npm.pdns"
volumes: volumes:
- '/etc/localtime:/etc/localtime:ro' - '/etc/localtime:/etc/localtime:ro'

View File

@@ -16,9 +16,6 @@ module.exports = defineConfig({
}, },
env: { env: {
swaggerBase: '{{baseUrl}}/api/schema', swaggerBase: '{{baseUrl}}/api/schema',
authentik: 'http://authentik:9000',
authentikLdap: 'authentik-ldap:3389',
oauthRedirect: 'http://fullstack:81',
}, },
baseUrl: 'http://localhost:1234', baseUrl: 'http://localhost:1234',
}, },

View File

@@ -7,7 +7,8 @@ module.exports = defineConfig({
reporterOptions: { reporterOptions: {
configFile: 'multi-reporter.json' configFile: 'multi-reporter.json'
}, },
video: false, video: true,
videosFolder: 'results/videos',
screenshotsFolder: 'results/screenshots', screenshotsFolder: 'results/screenshots',
e2e: { e2e: {
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
@@ -15,9 +16,7 @@ module.exports = defineConfig({
}, },
env: { env: {
swaggerBase: '{{baseUrl}}/api/schema', swaggerBase: '{{baseUrl}}/api/schema',
authentik: 'http://authentik:9000', skipStackCheck: 'true',
authentikLdap: 'authentik-ldap:3389',
oauthRedirect: 'http://npm:81',
}, },
} }
}); });

View File

@@ -2,7 +2,7 @@
describe('LDAP with Authentik', () => { describe('LDAP with Authentik', () => {
let token; let token;
if (Cypress.env('stack') === 'postgres') { if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => { before(() => {
cy.resetUsers(); cy.resetUsers();
@@ -14,7 +14,7 @@ describe('LDAP with Authentik', () => {
path: '/api/settings/ldap-auth', path: '/api/settings/ldap-auth',
data: { data: {
value: { value: {
host: Cypress.env('authentik-ldap'), host: 'authentik-ldap:3389',
base_dn: 'ou=users,DC=ldap,DC=goauthentik,DC=io', base_dn: 'ou=users,DC=ldap,DC=goauthentik,DC=io',
user_dn: 'cn={{USERNAME}},ou=users,DC=ldap,DC=goauthentik,DC=io', user_dn: 'cn={{USERNAME}},ou=users,DC=ldap,DC=goauthentik,DC=io',
email_property: 'mail', email_property: 'mail',

View File

@@ -2,7 +2,7 @@
describe('OAuth with Authentik', () => { describe('OAuth with Authentik', () => {
let token; let token;
if (Cypress.env('stack') === 'postgres') { if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => { before(() => {
cy.resetUsers(); cy.resetUsers();
@@ -14,12 +14,12 @@ describe('OAuth with Authentik', () => {
path: '/api/settings/oauth-auth', path: '/api/settings/oauth-auth',
data: { data: {
value: { value: {
client_id: 'U5gCy0ymU8OofWS4nmkAPugCbWkFkkPztap38ReD', client_id: '7iO2AvuUp9JxiSVkCcjiIbQn4mHmUMBj7yU8EjqU',
client_secret: '9ZFClxwp7LzbfhIDk7k9DngQNQfwDAYqPrQMGXjFumCvQZATtXCwme20o0TnLP6uEHUkKqEFOInhxp01gVeaHCLW83iTK4PonoUnpFnXgyZAcu0H3zBxxOkVtRwACaoW', client_secret: 'VUMZzaGTrmXJ8PLksyqzyZ6lrtz04VvejFhPMBP9hGZNCMrn2LLBanySs4ta7XGrDr05xexPyZT1XThaf4ubg00WqvHRVvlu4Naa1aMootNmSRx3VAk6RSslUJmGyHzq',
authorization_url: Cypress.env('authentik') + '/application/o/authorize/', authorization_url: 'http://authentik:9000/application/o/authorize/',
resource_url: Cypress.env('authentik') + '/application/o/userinfo/', resource_url: 'http://authentik:9000/application/o/userinfo/',
token_url: Cypress.env('authentik') + '/application/o/token/', token_url: 'http://authentik:9000/application/o/token/',
logout_url: Cypress.env('authentik') + '/application/o/npm3/end-session/', logout_url: 'http://authentik:9000/application/o/npm/end-session/',
identifier: 'preferred_username', identifier: 'preferred_username',
scopes: [], scopes: [],
auto_create_user: true auto_create_user: true
@@ -50,16 +50,48 @@ describe('OAuth with Authentik', () => {
it('Should log in with OAuth', function() { it('Should log in with OAuth', function() {
cy.task('backendApiGet', { cy.task('backendApiGet', {
token: token, path: '/oauth/login?redirect_base=' + encodeURI(Cypress.config('baseUrl')),
path: '/oauth/login?redirect_base=' + encodeURI(Cypress.env('oauthRedirect')),
}).then((data) => { }).then((data) => {
expect(data).to.have.property('result'); expect(data).to.have.property('result');
cy.visit(data.result);
cy.get('input[name="uidField"]').type('cypress'); cy.origin('http://authentik:9000', {args: data.result}, (url) => {
cy.get('button[type="submit"]').click(); cy.visit(url);
cy.get('input[name="password"]').type('fqXBfUYqHvYqiwBHWW7f'); cy.get('ak-flow-executor')
cy.get('button[type="submit"]').click(); .shadow()
cy.url().should('match', /fullstack/) .find('ak-stage-identification')
.shadow()
.find('input[name="uidField"]', { visible: true })
.type('cypress');
cy.get('ak-flow-executor')
.shadow()
.find('ak-stage-identification')
.shadow()
.find('button[type="submit"]', { visible: true })
.click();
cy.get('ak-flow-executor')
.shadow()
.find('ak-stage-password')
.shadow()
.find('input[name="password"]', { visible: true })
.type('fqXBfUYqHvYqiwBHWW7f');
cy.get('ak-flow-executor')
.shadow()
.find('ak-stage-password')
.shadow()
.find('button[type="submit"]', { visible: true })
.click();
})
// we should be logged in
cy.get('#root p.chakra-text')
.first()
.should('have.text', 'Nginx Proxy Manager');
// logout:
cy.clearLocalStorage();
}); });
}); });
} }

View File

@@ -14,8 +14,9 @@ describe('UI Setup and Login', () => {
cy.get('input[name="password"]').type('changeme'); cy.get('input[name="password"]').type('changeme');
cy.get('form button:last').click(); cy.get('form button:last').click();
// To fix after chakra change: cy.get('#root p.chakra-text')
// cy.get('.navbar-nav .avatar').should('be.visible'); .first()
.should('have.text', 'Nginx Proxy Manager');
// logout: // logout:
cy.clearLocalStorage(); cy.clearLocalStorage();

View File

@@ -1,5 +1,5 @@
{ {
"name": "test", "name": "npmtestsuite",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",