aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod15
-rw-r--r--go.sum176
-rw-r--r--internal/db/access_tokens.go24
-rw-r--r--internal/db/access_tokens_test.go21
-rw-r--r--internal/db/backup.go27
-rw-r--r--internal/db/backup_test.go2
-rw-r--r--internal/db/db.go111
-rw-r--r--internal/db/lfs.go4
-rw-r--r--internal/db/lfs_test.go3
-rw-r--r--internal/db/login_source_files.go11
-rw-r--r--internal/db/login_source_files_test.go2
-rw-r--r--internal/db/login_sources.go25
-rw-r--r--internal/db/login_sources_test.go36
-rw-r--r--internal/db/main_test.go58
-rw-r--r--internal/db/models.go6
-rw-r--r--internal/db/perms.go9
-rw-r--r--internal/db/repos.go19
-rw-r--r--internal/db/repos_test.go3
-rw-r--r--internal/db/two_factors.go22
-rw-r--r--internal/db/two_factors_test.go3
-rw-r--r--internal/db/users.go22
-rw-r--r--internal/db/users_test.go5
-rw-r--r--internal/dbutil/logger.go15
-rw-r--r--internal/dbutil/writer.go37
-rw-r--r--internal/dbutil/writer_test.go58
25 files changed, 431 insertions, 283 deletions
diff --git a/go.mod b/go.mod
index 33208172..770773cb 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,6 @@ go 1.14
require (
github.com/Masterminds/semver/v3 v3.1.0
github.com/bgentry/speakeasy v0.1.0 // indirect
- github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e // indirect
github.com/editorconfig/editorconfig-core-go/v2 v2.3.2
github.com/fatih/color v1.9.0 // indirect
github.com/go-macaron/binding v1.1.0
@@ -16,7 +15,6 @@ require (
github.com/go-macaron/i18n v0.5.0
github.com/go-macaron/session v0.0.0-20190805070824-1a3cdc6f5659
github.com/go-macaron/toolbox v0.0.0-20190813233741-94defb8383c6
- github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/gogs/git-module v1.1.3
@@ -27,12 +25,9 @@ require (
github.com/google/go-querystring v1.0.0 // indirect
github.com/issue9/identicon v1.0.1
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43
- github.com/jinzhu/gorm v1.9.12
github.com/json-iterator/go v1.1.10
github.com/klauspost/compress v1.8.6 // indirect
github.com/klauspost/cpuid v1.2.1 // indirect
- github.com/lib/pq v1.3.0 // indirect
- github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 // indirect
@@ -50,14 +45,13 @@ require (
github.com/sergi/go-diff v1.1.0
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stretchr/testify v1.6.1
- github.com/t-tiger/gorm-bulk-insert v1.3.0
github.com/unknwon/cae v1.0.0
github.com/unknwon/com v1.0.1
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e
github.com/urfave/cli v1.22.4
- golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
- golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582
+ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
+ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
golang.org/x/text v0.3.3
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
@@ -65,6 +59,11 @@ require (
gopkg.in/ini.v1 v1.56.0
gopkg.in/ldap.v2 v2.5.1
gopkg.in/macaron.v1 v1.3.9
+ gorm.io/driver/mysql v1.0.1
+ gorm.io/driver/postgres v1.0.0
+ gorm.io/driver/sqlite v1.1.1
+ gorm.io/driver/sqlserver v1.0.3
+ gorm.io/gorm v1.20.0
unknwon.dev/clog/v2 v2.1.2
xorm.io/builder v0.3.6
xorm.io/core v0.7.2
diff --git a/go.sum b/go.sum
index c45b3a64..facec230 100644
--- a/go.sum
+++ b/go.sum
@@ -4,12 +4,14 @@ cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7h
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
+github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
@@ -17,6 +19,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -27,11 +30,16 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
+github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -39,14 +47,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
-github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e h1:LzwWXEScfcTu7vUZNlDDWDARoSGEtvlDKK2BYHowNeE=
-github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
+github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/editorconfig/editorconfig-core-go/v2 v2.3.2 h1:j9GLz0kWF9+1T3IX0MOhhvzLtqhFOvIKLhZFxtY95Qc=
github.com/editorconfig/editorconfig-core-go/v2 v2.3.2/go.mod h1:+u4rFiKVvlbukHyJM76GYXqQcnHScxvQCuKpMLRtJVw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
@@ -78,23 +87,23 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
+github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
+github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561 h1:aBzukfDxQlCTVS0NBUjI5YA3iVeaZ9Tb5PxNrrIP1xs=
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8=
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk=
-github.com/gogs/git-module v1.1.1 h1:/taoHtOHLorlmQJ7zLBQvJGGgM9LRIoGGH1et4Upzvo=
-github.com/gogs/git-module v1.1.1/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
-github.com/gogs/git-module v1.1.2 h1:30jO+rKEmCDk/O6Mnl7MVrw6rI1qLDByXpkRB+bpYwM=
-github.com/gogs/git-module v1.1.2/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
github.com/gogs/git-module v1.1.3 h1:fMxxSvYwgaVDcYirFYlmhgm6MWTm2i4lG84NhIkSMR0=
github.com/gogs/git-module v1.1.3/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4 h1:C7NryI/RQhsIWwC2bHN601P1wJKeuQ6U/UCOYTn3Cic=
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0 h1:K02vod+sn3M1OOkdqi2tPxN2+xESK4qyITVQ3JkGEv4=
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0/go.mod h1:Zas3BtO88pk1cwUfEYlvnl/CRwh0ybDxRWSwRjG8I3w=
+github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a h1:8DZwxETOVWIinYxDK+i6L+rMb7eGATGaakD6ZucfHVk=
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a/go.mod h1:TUIZ+29jodWQ8Gk6Pvtg4E09aMsc3C/VLZiVYfUhWQU=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@@ -116,6 +125,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
@@ -124,9 +134,11 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
@@ -134,17 +146,70 @@ github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/issue9/assert v1.3.1 h1:L8pRpbnzMIPFJqrMKR/oG03uWrtVeZyYBpI2U2Jx1JE=
github.com/issue9/assert v1.3.1/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio=
github.com/issue9/identicon v1.0.1 h1:pCDfjMDM6xWK0Chxo8Lif+ST/nOEtmXgMITgV1YA9Og=
github.com/issue9/identicon v1.0.1/go.mod h1:UKNVkUFI68RPz/RlLhsAr1aX6bBSaYEWRHVfdjrMUmk=
+github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
+github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
+github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
+github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
+github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
+github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
+github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
+github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
+github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
+github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
+github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
+github.com/jackc/pgconn v1.6.4 h1:S7T6cx5o2OqmxdHaXLH1ZeD1SbI8jBznyYE9Ec0RCQ8=
+github.com/jackc/pgconn v1.6.4/go.mod h1:w2pne1C2tZgP+TvjqLpOigGzNqjBgQW9dUw/4Chex78=
+github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
+github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
+github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
+github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
+github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
+github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
+github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
+github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
+github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY=
+github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
+github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
+github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
+github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
+github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
+github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
+github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
+github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
+github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
+github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
+github.com/jackc/pgtype v1.4.2 h1:t+6LWm5eWPLX1H5Se702JSBcirq6uWa4jiG4wV1rAWY=
+github.com/jackc/pgtype v1.4.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
+github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
+github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
+github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
+github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
+github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
+github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
+github.com/jackc/pgx/v4 v4.8.1 h1:SUbCLP2pXvf/Sr/25KsuI4aTxiFYIvpfk4l6aTSdyCw=
+github.com/jackc/pgx/v4 v4.8.1/go.mod h1:4HOLxrl8wToZJReD04/yB20GDwf4KBYETvlHciCnwW0=
+github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43 h1:jTkyeF7NZ5oIr0ESmcrpiDgAfoidCBF4F5kJhjtaRwE=
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
+github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE=
github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw=
-github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
-github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
+github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -152,6 +217,7 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -160,20 +226,32 @@ github.com/klauspost/compress v1.8.6/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
+github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@@ -182,6 +260,7 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -190,8 +269,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 h1:YocNLcTBdEdvY3iDK6jfWXvEaM5OCKkjxPKoJRdB3Gg=
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
-github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
-github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -245,15 +322,23 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
+github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
+github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
+github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
+github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
@@ -261,29 +346,29 @@ github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
-github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
-github.com/t-tiger/gorm-bulk-insert v1.3.0 h1:9k7BaVEhw/3fsvh6GTOBwJ2RXk3asc5xs5m6hwozq20=
-github.com/t-tiger/gorm-bulk-insert v1.3.0/go.mod h1:ruDlk8xDl+8sX4bA7PQuYly9YEb3pbp1eP2LCyeRrFY=
github.com/unknwon/cae v1.0.0 h1:i39lOFaBXZxhGjQOy/RNbi8uzettCs6OQxpR0xXohGU=
github.com/unknwon/cae v1.0.0/go.mod h1:QaSeRctcea9fK6piJpAMCCPKxzJ01+xFcr2k1m3WRPU=
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
@@ -295,23 +380,41 @@ github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e h1:Qf3QQl/zmEbWD
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e/go.mod h1:TBwoao3Q4Eb/cp+dHbXDfRTrZSsj/k7kLr2j1oWRWC0=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
+github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
-golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -326,8 +429,10 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
-golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -335,6 +440,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -343,14 +449,19 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -364,14 +475,23 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190802220118-1d1727260058/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190805222050-c5a2fd39b72a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
+golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -390,6 +510,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
@@ -397,10 +518,13 @@ gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEH
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
+gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@@ -410,10 +534,6 @@ gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
gopkg.in/macaron.v1 v1.3.4/go.mod h1:/RoHTdC8ALpyJ3+QR36mKjwnT1F1dyYtsGM9Ate6ZFI=
gopkg.in/macaron.v1 v1.3.5/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
-gopkg.in/macaron.v1 v1.3.6 h1:mHw5qRGj2f86sCjBV/S5OOPvPbiZpu0OEs1F5l66fYI=
-gopkg.in/macaron.v1 v1.3.6/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
-gopkg.in/macaron.v1 v1.3.8 h1:45bQT4dDF+5SLd75qlj+dulQsuFQ9aFyLlvZX6YUJWE=
-gopkg.in/macaron.v1 v1.3.8/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
gopkg.in/macaron.v1 v1.3.9 h1:Dw+DDRYdXgQyEsPlfAfKz+UA5qVUrH3KPD7JhmZ9MFc=
gopkg.in/macaron.v1 v1.3.9/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
gopkg.in/redis.v2 v2.3.2 h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs=
@@ -425,9 +545,21 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/mysql v1.0.1 h1:omJoilUzyrAp0xNoio88lGJCroGdIOen9hq2A/+3ifw=
+gorm.io/driver/mysql v1.0.1/go.mod h1:KtqSthtg55lFp3S5kUXqlGaelnWpKitn4k1xZTnoiPw=
+gorm.io/driver/postgres v1.0.0 h1:Yh4jyFQ0a7F+JPU0Gtiam/eKmpT/XFc1FKxotGqc6FM=
+gorm.io/driver/postgres v1.0.0/go.mod h1:wtMFcOzmuA5QigNsgEIb7O5lhvH1tHAF1RbWmLWV4to=
+gorm.io/driver/sqlite v1.1.1 h1:qtWqNAEUyi7gYSUAJXeiAMz0lUOdakZF5ia9Fqnp5G4=
+gorm.io/driver/sqlite v1.1.1/go.mod h1:hm2olEcl8Tmsc6eZyxYSeznnsDaMqamBvEXLNtBg4cI=
+gorm.io/driver/sqlserver v1.0.3 h1:Al16r8X+57ZNcZBqrEwcakCF1mBChuwZW72O8WgJKnk=
+gorm.io/driver/sqlserver v1.0.3/go.mod h1:gb0Y9QePGgqjzrVyTQUZeh9zkd5v0iz71cM1B4ZycEY=
+gorm.io/gorm v1.9.19/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.20.0 h1:qfIlyaZvrF7kMWY3jBdEBXkXJ2M5MFYMTppjILxS3fQ=
+gorm.io/gorm v1.20.0/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
unknwon.dev/clog/v2 v2.1.2 h1:+jwPPp10UtOPunFtviUmXF01Abf6q7p5GEy4jluLl8o=
unknwon.dev/clog/v2 v2.1.2/go.mod h1:zvUlyibDHI4mykYdWyWje2G9nF/nBzfDOqRo2my4mWc=
xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8=
diff --git a/internal/db/access_tokens.go b/internal/db/access_tokens.go
index 115f0105..ab62c52d 100644
--- a/internal/db/access_tokens.go
+++ b/internal/db/access_tokens.go
@@ -8,8 +8,8 @@ import (
"fmt"
"time"
- "github.com/jinzhu/gorm"
gouuid "github.com/satori/go.uuid"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/cryptoutil"
"gogs.io/gogs/internal/errutil"
@@ -55,24 +55,26 @@ type AccessToken struct {
}
// NOTE: This is a GORM create hook.
-func (t *AccessToken) BeforeCreate() {
- if t.CreatedUnix > 0 {
- return
+func (t *AccessToken) BeforeCreate(tx *gorm.DB) error {
+ if t.CreatedUnix == 0 {
+ t.CreatedUnix = tx.NowFunc().Unix()
}
- t.CreatedUnix = gorm.NowFunc().Unix()
+ return nil
}
// NOTE: This is a GORM update hook.
-func (t *AccessToken) BeforeUpdate() {
- t.UpdatedUnix = gorm.NowFunc().Unix()
+func (t *AccessToken) BeforeUpdate(tx *gorm.DB) error {
+ t.UpdatedUnix = tx.NowFunc().Unix()
+ return nil
}
// NOTE: This is a GORM query hook.
-func (t *AccessToken) AfterFind() {
+func (t *AccessToken) AfterFind(tx *gorm.DB) error {
t.Created = time.Unix(t.CreatedUnix, 0).Local()
t.Updated = time.Unix(t.UpdatedUnix, 0).Local()
t.HasUsed = t.Updated.After(t.Created)
- t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(gorm.NowFunc())
+ t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(tx.NowFunc())
+ return nil
}
var _ AccessTokensStore = (*accessTokens)(nil)
@@ -98,7 +100,7 @@ func (db *accessTokens) Create(userID int64, name string) (*AccessToken, error)
err := db.Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
if err == nil {
return nil, ErrAccessTokenAlreadyExist{args: errutil.Args{"userID": userID, "name": name}}
- } else if !gorm.IsRecordNotFoundError(err) {
+ } else if err != gorm.ErrRecordNotFound {
return nil, err
}
@@ -137,7 +139,7 @@ func (db *accessTokens) GetBySHA(sha string) (*AccessToken, error) {
token := new(AccessToken)
err := db.Where("sha1 = ?", sha).First(token).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha}}
}
return nil, err
diff --git a/internal/db/access_tokens_test.go b/internal/db/access_tokens_test.go
index 8a2f3805..ef629320 100644
--- a/internal/db/access_tokens_test.go
+++ b/internal/db/access_tokens_test.go
@@ -8,24 +8,33 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
)
func TestAccessToken_BeforeCreate(t *testing.T) {
+ now := time.Now()
+ db := &gorm.DB{
+ Config: &gorm.Config{
+ NowFunc: func() time.Time {
+ return now
+ },
+ },
+ }
+
t.Run("CreatedUnix has been set", func(t *testing.T) {
token := &AccessToken{CreatedUnix: 1}
- token.BeforeCreate()
+ _ = token.BeforeCreate(db)
assert.Equal(t, int64(1), token.CreatedUnix)
assert.Equal(t, int64(0), token.UpdatedUnix)
})
t.Run("CreatedUnix has not been set", func(t *testing.T) {
token := &AccessToken{}
- token.BeforeCreate()
- assert.Equal(t, gorm.NowFunc().Unix(), token.CreatedUnix)
+ _ = token.BeforeCreate(db)
+ assert.Equal(t, db.NowFunc().Unix(), token.CreatedUnix)
assert.Equal(t, int64(0), token.UpdatedUnix)
})
}
@@ -80,7 +89,7 @@ func test_accessTokens_Create(t *testing.T, db *accessTokens) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), token.Created.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), token.Created.UTC().Format(time.RFC3339))
// Try create second access token with same name should fail
_, err = db.Create(token.UserID, token.Name)
@@ -193,5 +202,5 @@ func test_accessTokens_Save(t *testing.T, db *accessTokens) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), token.Updated.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), token.Updated.UTC().Format(time.RFC3339))
}
diff --git a/internal/db/backup.go b/internal/db/backup.go
index a02d70d6..985b3c0f 100644
--- a/internal/db/backup.go
+++ b/internal/db/backup.go
@@ -8,10 +8,12 @@ import (
"path/filepath"
"reflect"
"strings"
+ "sync"
- "github.com/jinzhu/gorm"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
+ "gorm.io/gorm"
+ "gorm.io/gorm/schema"
log "unknwon.dev/clog/v2"
"xorm.io/core"
"xorm.io/xorm"
@@ -153,17 +155,21 @@ func ImportDatabase(db *gorm.DB, dirPath string, verbose bool) error {
}
func importTable(db *gorm.DB, table interface{}, r io.Reader) error {
- err := db.DropTableIfExists(table).Error
+ err := db.Migrator().DropTable(table)
if err != nil {
return errors.Wrap(err, "drop table")
}
- err = db.AutoMigrate(table).Error
+ err = db.Migrator().AutoMigrate(table)
if err != nil {
return errors.Wrap(err, "auto migrate")
}
- rawTableName := db.NewScope(table).TableName()
+ s, err := schema.Parse(table, &sync.Map{}, db.NamingStrategy)
+ if err != nil {
+ return errors.Wrap(err, "parse schema")
+ }
+ rawTableName := s.Table
skipResetIDSeq := map[string]bool{
"lfs_object": true,
}
@@ -235,21 +241,26 @@ func importLegacyTables(dirPath string, verbose bool) error {
return fmt.Errorf("insert strcut: %v", err)
}
- meta := make(map[string]interface{})
+ var meta struct {
+ ID int64
+ CreatedUnix int64
+ DeadlineUnix int64
+ ClosedDateUnix int64
+ }
if err = jsoniter.Unmarshal(scanner.Bytes(), &meta); err != nil {
log.Error("Failed to unmarshal to map: %v", err)
}
// Reset created_unix back to the date save in archive because Insert method updates its value
if isInsertProcessor && !skipInsertProcessors[rawTableName] {
- if _, err = x.Exec("UPDATE `"+rawTableName+"` SET created_unix=? WHERE id=?", meta["CreatedUnix"], meta["ID"]); err != nil {
- log.Error("Failed to reset 'created_unix': %v", err)
+ if _, err = x.Exec("UPDATE `"+rawTableName+"` SET created_unix=? WHERE id=?", meta.CreatedUnix, meta.ID); err != nil {
+ log.Error("Failed to reset '%s.created_unix': %v", rawTableName, err)
}
}
switch rawTableName {
case "milestone":
- if _, err = x.Exec("UPDATE `"+rawTableName+"` SET deadline_unix=?, closed_date_unix=? WHERE id=?", meta["DeadlineUnix"], meta["ClosedDateUnix"], meta["ID"]); err != nil {
+ if _, err = x.Exec("UPDATE `"+rawTableName+"` SET deadline_unix=?, closed_date_unix=? WHERE id=?", meta.DeadlineUnix, meta.ClosedDateUnix, meta.ID); err != nil {
log.Error("Failed to reset 'milestone.deadline_unix', 'milestone.closed_date_unix': %v", err)
}
}
diff --git a/internal/db/backup_test.go b/internal/db/backup_test.go
index 334b8d7d..fafaf28a 100644
--- a/internal/db/backup_test.go
+++ b/internal/db/backup_test.go
@@ -11,8 +11,8 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/pkg/errors"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/cryptoutil"
"gogs.io/gogs/internal/lfsutil"
diff --git a/internal/db/db.go b/internal/db/db.go
index a6e53683..03da40ca 100644
--- a/internal/db/db.go
+++ b/internal/db/db.go
@@ -6,18 +6,19 @@ package db
import (
"fmt"
- "io"
"net/url"
"path/filepath"
"strings"
"time"
- "github.com/jinzhu/gorm"
- _ "github.com/jinzhu/gorm/dialects/mssql"
- _ "github.com/jinzhu/gorm/dialects/mysql"
- _ "github.com/jinzhu/gorm/dialects/postgres"
- _ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/pkg/errors"
+ "gorm.io/driver/mysql"
+ "gorm.io/driver/postgres"
+ "gorm.io/driver/sqlite"
+ "gorm.io/driver/sqlserver"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+ "gorm.io/gorm/schema"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
@@ -96,16 +97,7 @@ func parseDSN(opts conf.DatabaseOpts) (dsn string, err error) {
return dsn, nil
}
-func openDB(opts conf.DatabaseOpts) (*gorm.DB, error) {
- dsn, err := parseDSN(opts)
- if err != nil {
- return nil, errors.Wrap(err, "parse DSN")
- }
-
- return gorm.Open(opts.Type, dsn)
-}
-
-func getLogWriter() (io.Writer, error) {
+func newLogWriter() (logger.Writer, error) {
sec := conf.File.Section("log.gorm")
w, err := log.NewFileWriter(
filepath.Join(conf.Log.RootPath, "gorm.log"),
@@ -119,7 +111,30 @@ func getLogWriter() (io.Writer, error) {
if err != nil {
return nil, errors.Wrap(err, `create "gorm.log"`)
}
- return w, nil
+ return &dbutil.Logger{Writer: w}, nil
+}
+
+func openDB(opts conf.DatabaseOpts, cfg *gorm.Config) (*gorm.DB, error) {
+ dsn, err := parseDSN(opts)
+ if err != nil {
+ return nil, errors.Wrap(err, "parse DSN")
+ }
+
+ var dialector gorm.Dialector
+ switch opts.Type {
+ case "mysql":
+ dialector = mysql.Open(dsn)
+ case "postgres":
+ dialector = postgres.Open(dsn)
+ case "mssql":
+ dialector = sqlserver.Open(dsn)
+ case "sqlite3":
+ dialector = sqlite.Open(dsn)
+ default:
+ panic("unreachable")
+ }
+
+ return gorm.Open(dialector, cfg)
}
// NOTE: Lines are sorted in alphabetical order, each letter in its own line.
@@ -129,56 +144,72 @@ var tables = []interface{}{
}
func Init() (*gorm.DB, error) {
- db, err := openDB(conf.Database)
+ w, err := newLogWriter()
if err != nil {
- return nil, errors.Wrap(err, "open database")
+ return nil, errors.Wrap(err, "new log writer")
+ }
+
+ level := logger.Info
+ if conf.IsProdMode() {
+ level = logger.Warn
}
- db.SingularTable(true)
- db.DB().SetMaxOpenConns(conf.Database.MaxOpenConns)
- db.DB().SetMaxIdleConns(conf.Database.MaxIdleConns)
- db.DB().SetConnMaxLifetime(time.Minute)
- w, err := getLogWriter()
+ // NOTE: AutoMigrate does not respect logger passed in gorm.Config.
+ logger.Default = logger.New(w, logger.Config{
+ SlowThreshold: 100 * time.Millisecond,
+ LogLevel: level,
+ })
+
+ db, err := openDB(conf.Database, &gorm.Config{
+ NamingStrategy: schema.NamingStrategy{
+ SingularTable: true,
+ },
+ NowFunc: func() time.Time {
+ return time.Now().UTC().Truncate(time.Microsecond)
+ },
+ })
if err != nil {
- return nil, errors.Wrap(err, "get log writer")
+ return nil, errors.Wrap(err, "open database")
}
- db.SetLogger(&dbutil.Writer{Writer: w})
- if !conf.IsProdMode() {
- db = db.LogMode(true)
+
+ sqlDB, err := db.DB()
+ if err != nil {
+ return nil, errors.Wrap(err, "get underlying *sql.DB")
}
+ sqlDB.SetMaxOpenConns(conf.Database.MaxOpenConns)
+ sqlDB.SetMaxIdleConns(conf.Database.MaxIdleConns)
+ sqlDB.SetConnMaxLifetime(time.Minute)
switch conf.Database.Type {
+ case "postgres":
+ conf.UsePostgreSQL = true
case "mysql":
conf.UseMySQL = true
db = db.Set("gorm:table_options", "ENGINE=InnoDB")
- case "postgres":
- conf.UsePostgreSQL = true
- case "mssql":
- conf.UseMSSQL = true
case "sqlite3":
conf.UseSQLite3 = true
+ case "mssql":
+ conf.UseMSSQL = true
+ default:
+ panic("unreachable")
}
// NOTE: GORM has problem detecting existing columns, see https://github.com/gogs/gogs/issues/6091.
// Therefore only use it to create new tables, and do customized migration with future changes.
for _, table := range tables {
- if db.HasTable(table) {
+ if db.Migrator().HasTable(table) {
continue
}
name := strings.TrimPrefix(fmt.Sprintf("%T", table), "*db.")
- err = db.AutoMigrate(table).Error
+ err = db.Migrator().AutoMigrate(table)
if err != nil {
return nil, errors.Wrapf(err, "auto migrate %q", name)
}
log.Trace("Auto migrated %q", name)
}
- gorm.NowFunc = func() time.Time {
- return time.Now().UTC().Truncate(time.Microsecond)
- }
-
- sourceFiles, err := loadLoginSourceFiles(filepath.Join(conf.CustomDir(), "conf", "auth.d"))
+ sourceFiles, err := loadLoginSourceFiles(filepath.Join(conf.CustomDir(), "conf", "auth.d"), db.NowFunc)
if err != nil {
return nil, errors.Wrap(err, "load login source files")
}
@@ -192,5 +223,5 @@ func Init() (*gorm.DB, error) {
TwoFactors = &twoFactors{DB: db}
Users = &users{DB: db}
- return db, db.DB().Ping()
+ return db, nil
}
diff --git a/internal/db/lfs.go b/internal/db/lfs.go
index 4db2fa2d..43515d8c 100644
--- a/internal/db/lfs.go
+++ b/internal/db/lfs.go
@@ -8,7 +8,7 @@ import (
"fmt"
"time"
- "github.com/jinzhu/gorm"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/lfsutil"
@@ -76,7 +76,7 @@ func (db *lfs) GetObjectByOID(repoID int64, oid lfsutil.OID) (*LFSObject, error)
object := new(LFSObject)
err := db.Where("repo_id = ? AND oid = ?", repoID, oid).First(object).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrLFSObjectNotExist{args: errutil.Args{"repoID": repoID, "oid": oid}}
}
return nil, err
diff --git a/internal/db/lfs_test.go b/internal/db/lfs_test.go
index 49d94406..4aff4f22 100644
--- a/internal/db/lfs_test.go
+++ b/internal/db/lfs_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
"gogs.io/gogs/internal/errutil"
@@ -61,7 +60,7 @@ func test_lfs_CreateObject(t *testing.T, db *lfs) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), object.CreatedAt.Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), object.CreatedAt.Format(time.RFC3339))
// Try create second LFS object with same oid should fail
err = db.CreateObject(repoID, oid, 12, lfsutil.StorageLocal)
diff --git a/internal/db/login_source_files.go b/internal/db/login_source_files.go
index 4c5cb377..f2a24ad9 100644
--- a/internal/db/login_source_files.go
+++ b/internal/db/login_source_files.go
@@ -10,8 +10,8 @@ import (
"path/filepath"
"strings"
"sync"
+ "time"
- "github.com/jinzhu/gorm"
"github.com/pkg/errors"
"gopkg.in/ini.v1"
@@ -39,6 +39,7 @@ var _ loginSourceFilesStore = (*loginSourceFiles)(nil)
type loginSourceFiles struct {
sync.RWMutex
sources []*LoginSource
+ clock func() time.Time
}
var _ errutil.NotFound = (*ErrLoginSourceNotExist)(nil)
@@ -98,7 +99,7 @@ func (s *loginSourceFiles) Update(source *LoginSource) {
s.Lock()
defer s.Unlock()
- source.Updated = gorm.NowFunc()
+ source.Updated = s.clock()
for _, old := range s.sources {
if old.ID == source.ID {
*old = *source
@@ -109,12 +110,12 @@ func (s *loginSourceFiles) Update(source *LoginSource) {
}
// loadLoginSourceFiles loads login sources from file system.
-func loadLoginSourceFiles(authdPath string) (loginSourceFilesStore, error) {
+func loadLoginSourceFiles(authdPath string, clock func() time.Time) (loginSourceFilesStore, error) {
if !osutil.IsDir(authdPath) {
- return &loginSourceFiles{}, nil
+ return &loginSourceFiles{clock: clock}, nil
}
- store := &loginSourceFiles{}
+ store := &loginSourceFiles{clock: clock}
return store, filepath.Walk(authdPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
diff --git a/internal/db/login_source_files_test.go b/internal/db/login_source_files_test.go
index d87239a8..d9cdc788 100644
--- a/internal/db/login_source_files_test.go
+++ b/internal/db/login_source_files_test.go
@@ -6,6 +6,7 @@ package db
import (
"testing"
+ "time"
"github.com/stretchr/testify/assert"
@@ -70,6 +71,7 @@ func Test_loginSourceFiles_Update(t *testing.T) {
{ID: 101, IsActived: true, IsDefault: true},
{ID: 102, IsActived: false},
},
+ clock: time.Now,
}
source102 := &LoginSource{
diff --git a/internal/db/login_sources.go b/internal/db/login_sources.go
index 3c47a14c..4bb1f4c2 100644
--- a/internal/db/login_sources.go
+++ b/internal/db/login_sources.go
@@ -9,9 +9,9 @@ import (
"strconv"
"time"
- "github.com/jinzhu/gorm"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/auth/ldap"
"gogs.io/gogs/internal/errutil"
@@ -62,7 +62,7 @@ type LoginSource struct {
}
// NOTE: This is a GORM save hook.
-func (s *LoginSource) BeforeSave() (err error) {
+func (s *LoginSource) BeforeSave(tx *gorm.DB) (err error) {
if s.Config == nil {
return nil
}
@@ -71,21 +71,22 @@ func (s *LoginSource) BeforeSave() (err error) {
}
// NOTE: This is a GORM create hook.
-func (s *LoginSource) BeforeCreate() {
- if s.CreatedUnix > 0 {
- return
+func (s *LoginSource) BeforeCreate(tx *gorm.DB) error {
+ if s.CreatedUnix == 0 {
+ s.CreatedUnix = tx.NowFunc().Unix()
+ s.UpdatedUnix = s.CreatedUnix
}
- s.CreatedUnix = gorm.NowFunc().Unix()
- s.UpdatedUnix = s.CreatedUnix
+ return nil
}
// NOTE: This is a GORM update hook.
-func (s *LoginSource) BeforeUpdate() {
- s.UpdatedUnix = gorm.NowFunc().Unix()
+func (s *LoginSource) BeforeUpdate(tx *gorm.DB) error {
+ s.UpdatedUnix = tx.NowFunc().Unix()
+ return nil
}
// NOTE: This is a GORM query hook.
-func (s *LoginSource) AfterFind() error {
+func (s *LoginSource) AfterFind(tx *gorm.DB) error {
s.Created = time.Unix(s.CreatedUnix, 0).Local()
s.Updated = time.Unix(s.UpdatedUnix, 0).Local()
@@ -204,7 +205,7 @@ func (db *loginSources) Create(opts CreateLoginSourceOpts) (*LoginSource, error)
err := db.Where("name = ?", opts.Name).First(new(LoginSource)).Error
if err == nil {
return nil, ErrLoginSourceAlreadyExist{args: errutil.Args{"name": opts.Name}}
- } else if !gorm.IsRecordNotFoundError(err) {
+ } else if err != gorm.ErrRecordNotFound {
return nil, err
}
@@ -253,7 +254,7 @@ func (db *loginSources) GetByID(id int64) (*LoginSource, error) {
source := new(LoginSource)
err := db.Where("id = ?", id).First(source).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return db.files.GetByID(id)
}
return nil, err
diff --git a/internal/db/login_sources_test.go b/internal/db/login_sources_test.go
index ac657add..cb3a16e7 100644
--- a/internal/db/login_sources_test.go
+++ b/internal/db/login_sources_test.go
@@ -8,16 +8,25 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
)
func TestLoginSource_BeforeSave(t *testing.T) {
+ now := time.Now()
+ db := &gorm.DB{
+ Config: &gorm.Config{
+ NowFunc: func() time.Time {
+ return now
+ },
+ },
+ }
+
t.Run("Config has not been set", func(t *testing.T) {
s := &LoginSource{}
- err := s.BeforeSave()
+ err := s.BeforeSave(db)
if err != nil {
t.Fatal(err)
}
@@ -28,7 +37,7 @@ func TestLoginSource_BeforeSave(t *testing.T) {
s := &LoginSource{
Config: &PAMConfig{ServiceName: "pam_service"},
}
- err := s.BeforeSave()
+ err := s.BeforeSave(db)
if err != nil {
t.Fatal(err)
}
@@ -37,18 +46,27 @@ func TestLoginSource_BeforeSave(t *testing.T) {
}
func TestLoginSource_BeforeCreate(t *testing.T) {
+ now := time.Now()
+ db := &gorm.DB{
+ Config: &gorm.Config{
+ NowFunc: func() time.Time {
+ return now
+ },
+ },
+ }
+
t.Run("CreatedUnix has been set", func(t *testing.T) {
s := &LoginSource{CreatedUnix: 1}
- s.BeforeCreate()
+ _ = s.BeforeCreate(db)
assert.Equal(t, int64(1), s.CreatedUnix)
assert.Equal(t, int64(0), s.UpdatedUnix)
})
t.Run("CreatedUnix has not been set", func(t *testing.T) {
s := &LoginSource{}
- s.BeforeCreate()
- assert.Equal(t, gorm.NowFunc().Unix(), s.CreatedUnix)
- assert.Equal(t, gorm.NowFunc().Unix(), s.UpdatedUnix)
+ _ = s.BeforeCreate(db)
+ assert.Equal(t, db.NowFunc().Unix(), s.CreatedUnix)
+ assert.Equal(t, db.NowFunc().Unix(), s.UpdatedUnix)
})
}
@@ -108,8 +126,8 @@ func test_loginSources_Create(t *testing.T, db *loginSources) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), source.Created.UTC().Format(time.RFC3339))
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), source.Updated.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), source.Created.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), source.Updated.UTC().Format(time.RFC3339))
// Try create second login source with same name should fail
_, err = db.Create(CreateLoginSourceOpts{Name: source.Name})
diff --git a/internal/db/main_test.go b/internal/db/main_test.go
index 6813118e..09f175c5 100644
--- a/internal/db/main_test.go
+++ b/internal/db/main_test.go
@@ -8,12 +8,15 @@ import (
"flag"
"fmt"
"io/ioutil"
+ stdlog "log"
"os"
"path/filepath"
"testing"
"time"
- "github.com/jinzhu/gorm"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+ "gorm.io/gorm/schema"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
@@ -21,10 +24,11 @@ import (
"gogs.io/gogs/internal/testutil"
)
-var printSQL = flag.Bool("print-sql", false, "Print SQL executed")
-
func TestMain(m *testing.M) {
flag.Parse()
+
+ var w logger.Writer
+ level := logger.Silent
if !testing.Verbose() {
// Remove the primary logger and register a noop logger.
log.Remove(log.DefaultConsoleName)
@@ -33,10 +37,18 @@ func TestMain(m *testing.M) {
fmt.Println(err)
os.Exit(1)
}
+
+ w = &dbutil.Logger{Writer: ioutil.Discard}
+ } else {
+ w = stdlog.New(os.Stdout, "\r\n", stdlog.LstdFlags)
+ level = logger.Info
}
- now := time.Now().UTC().Truncate(time.Second)
- gorm.NowFunc = func() time.Time { return now }
+ // NOTE: AutoMigrate does not respect logger passed in gorm.Config.
+ logger.Default = logger.New(w, logger.Config{
+ SlowThreshold: 100 * time.Millisecond,
+ LogLevel: level,
+ })
os.Exit(m.Run())
}
@@ -48,7 +60,7 @@ func clearTables(t *testing.T, db *gorm.DB, tables ...interface{}) error {
}
for _, t := range tables {
- err := db.Delete(t).Error
+ err := db.Where("TRUE").Delete(t).Error
if err != nil {
return err
}
@@ -60,15 +72,29 @@ func initTestDB(t *testing.T, suite string, tables ...interface{}) *gorm.DB {
t.Helper()
dbpath := filepath.Join(os.TempDir(), fmt.Sprintf("gogs-%s-%d.db", suite, time.Now().Unix()))
- db, err := openDB(conf.DatabaseOpts{
- Type: "sqlite3",
- Path: dbpath,
- })
+ now := time.Now().UTC().Truncate(time.Second)
+ db, err := openDB(
+ conf.DatabaseOpts{
+ Type: "sqlite3",
+ Path: dbpath,
+ },
+ &gorm.Config{
+ NamingStrategy: schema.NamingStrategy{
+ SingularTable: true,
+ },
+ NowFunc: func() time.Time {
+ return now
+ },
+ },
+ )
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
- _ = db.Close()
+ sqlDB, err := db.DB()
+ if err == nil {
+ _ = sqlDB.Close()
+ }
if t.Failed() {
t.Logf("Database %q left intact for inspection", dbpath)
@@ -78,15 +104,7 @@ func initTestDB(t *testing.T, suite string, tables ...interface{}) *gorm.DB {
_ = os.Remove(dbpath)
})
- db.SingularTable(true)
- if !testing.Verbose() {
- db.SetLogger(&dbutil.Writer{Writer: ioutil.Discard})
- }
- if *printSQL {
- db.LogMode(true)
- }
-
- err = db.AutoMigrate(tables...).Error
+ err = db.Migrator().AutoMigrate(tables...)
if err != nil {
t.Fatal(err)
}
diff --git a/internal/db/models.go b/internal/db/models.go
index d2868bb6..52ef4495 100644
--- a/internal/db/models.go
+++ b/internal/db/models.go
@@ -13,7 +13,7 @@ import (
"strings"
"time"
- "github.com/jinzhu/gorm"
+ "gorm.io/gorm"
log "unknwon.dev/clog/v2"
"xorm.io/core"
"xorm.io/xorm"
@@ -68,6 +68,7 @@ func getEngine() (*xorm.Engine, error) {
Param = "&"
}
+ driver := conf.Database.Type
connStr := ""
switch conf.Database.Type {
case "mysql":
@@ -92,6 +93,7 @@ func getEngine() (*xorm.Engine, error) {
connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
url.QueryEscape(conf.Database.User), url.QueryEscape(conf.Database.Password), host, port, conf.Database.Name, Param, conf.Database.SSLMode)
}
+ driver = "pgx"
case "mssql":
conf.UseMSSQL = true
@@ -108,7 +110,7 @@ func getEngine() (*xorm.Engine, error) {
default:
return nil, fmt.Errorf("unknown database type: %s", conf.Database.Type)
}
- return xorm.NewEngine(conf.Database.Type, connStr)
+ return xorm.NewEngine(driver, connStr)
}
func NewTestEngine() error {
diff --git a/internal/db/perms.go b/internal/db/perms.go
index 129f2187..1295300d 100644
--- a/internal/db/perms.go
+++ b/internal/db/perms.go
@@ -5,8 +5,7 @@
package db
import (
- "github.com/jinzhu/gorm"
- "github.com/t-tiger/gorm-bulk-insert"
+ "gorm.io/gorm"
log "unknwon.dev/clog/v2"
)
@@ -53,7 +52,7 @@ func (db *perms) AccessMode(userID int64, repo *Repository) (mode AccessMode) {
access := new(Access)
err := db.Where("user_id = ? AND repo_id = ?", userID, repo.ID).First(access).Error
if err != nil {
- if !gorm.IsRecordNotFoundError(err) {
+ if err != gorm.ErrRecordNotFound {
log.Error("Failed to get access [user_id: %d, repo_id: %d]: %v", userID, repo.ID, err)
}
return mode
@@ -66,7 +65,7 @@ func (db *perms) Authorize(userID int64, repo *Repository, desired AccessMode) b
}
func (db *perms) SetRepoPerms(repoID int64, accessMap map[int64]AccessMode) error {
- records := make([]interface{}, 0, len(accessMap))
+ records := make([]*Access, 0, len(accessMap))
for userID, mode := range accessMap {
records = append(records, &Access{
UserID: userID,
@@ -81,6 +80,6 @@ func (db *perms) SetRepoPerms(repoID int64, accessMap map[int64]AccessMode) erro
return err
}
- return gormbulk.BulkInsert(tx, records, 3000)
+ return tx.Create(&records).Error
})
}
diff --git a/internal/db/repos.go b/internal/db/repos.go
index 08cc6485..fc5bce03 100644
--- a/internal/db/repos.go
+++ b/internal/db/repos.go
@@ -9,7 +9,7 @@ import (
"strings"
"time"
- "github.com/jinzhu/gorm"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
)
@@ -26,19 +26,24 @@ type ReposStore interface {
var Repos ReposStore
// NOTE: This is a GORM create hook.
-func (r *Repository) BeforeCreate() {
- r.CreatedUnix = gorm.NowFunc().Unix()
+func (r *Repository) BeforeCreate(tx *gorm.DB) error {
+ if r.CreatedUnix == 0 {
+ r.CreatedUnix = tx.NowFunc().Unix()
+ }
+ return nil
}
// NOTE: This is a GORM update hook.
-func (r *Repository) BeforeUpdate() {
- r.UpdatedUnix = gorm.NowFunc().Unix()
+func (r *Repository) BeforeUpdate(tx *gorm.DB) error {
+ r.UpdatedUnix = tx.NowFunc().Unix()
+ return nil
}
// NOTE: This is a GORM query hook.
-func (r *Repository) AfterFind() {
+func (r *Repository) AfterFind(tx *gorm.DB) error {
r.Created = time.Unix(r.CreatedUnix, 0).Local()
r.Updated = time.Unix(r.UpdatedUnix, 0).Local()
+ return nil
}
var _ ReposStore = (*repos)(nil)
@@ -129,7 +134,7 @@ func (db *repos) GetByName(ownerID int64, name string) (*Repository, error) {
repo := new(Repository)
err := db.Where("owner_id = ? AND lower_name = ?", ownerID, strings.ToLower(name)).First(repo).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "name": name}}
}
return nil, err
diff --git a/internal/db/repos_test.go b/internal/db/repos_test.go
index 42eedbba..7b8f2b00 100644
--- a/internal/db/repos_test.go
+++ b/internal/db/repos_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
"gogs.io/gogs/internal/errutil"
@@ -80,7 +79,7 @@ func test_repos_create(t *testing.T, db *repos) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), repo.Created.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), repo.Created.UTC().Format(time.RFC3339))
}
func test_repos_GetByName(t *testing.T, db *repos) {
diff --git a/internal/db/two_factors.go b/internal/db/two_factors.go
index aa90c2ff..7692e5d5 100644
--- a/internal/db/two_factors.go
+++ b/internal/db/two_factors.go
@@ -10,9 +10,8 @@ import (
"strings"
"time"
- "github.com/jinzhu/gorm"
"github.com/pkg/errors"
- "github.com/t-tiger/gorm-bulk-insert"
+ "gorm.io/gorm"
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/cryptoutil"
@@ -39,13 +38,17 @@ type TwoFactorsStore interface {
var TwoFactors TwoFactorsStore
// NOTE: This is a GORM create hook.
-func (t *TwoFactor) BeforeCreate() {
- t.CreatedUnix = gorm.NowFunc().Unix()
+func (t *TwoFactor) BeforeCreate(tx *gorm.DB) error {
+ if t.CreatedUnix == 0 {
+ t.CreatedUnix = tx.NowFunc().Unix()
+ }
+ return nil
}
// NOTE: This is a GORM query hook.
-func (t *TwoFactor) AfterFind() {
+func (t *TwoFactor) AfterFind(tx *gorm.DB) error {
t.Created = time.Unix(t.CreatedUnix, 0).Local()
+ return nil
}
var _ TwoFactorsStore = (*twoFactors)(nil)
@@ -69,18 +72,13 @@ func (db *twoFactors) Create(userID int64, key, secret string) error {
return errors.Wrap(err, "generate recovery codes")
}
- records := make([]interface{}, 0, len(recoveryCodes))
- for _, code := range recoveryCodes {
- records = append(records, code)
- }
-
return db.Transaction(func(tx *gorm.DB) error {
err := tx.Create(tf).Error
if err != nil {
return err
}
- return gormbulk.BulkInsert(tx, records, 3000)
+ return tx.Create(&recoveryCodes).Error
})
}
@@ -107,7 +105,7 @@ func (db *twoFactors) GetByUserID(userID int64) (*TwoFactor, error) {
tf := new(TwoFactor)
err := db.Where("user_id = ?", userID).First(tf).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrTwoFactorNotFound{args: errutil.Args{"userID": userID}}
}
return nil, err
diff --git a/internal/db/two_factors_test.go b/internal/db/two_factors_test.go
index 4f0ad9da..20dfae61 100644
--- a/internal/db/two_factors_test.go
+++ b/internal/db/two_factors_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
"gogs.io/gogs/internal/errutil"
@@ -58,7 +57,7 @@ func test_twoFactors_Create(t *testing.T, db *twoFactors) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), tf.Created.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), tf.Created.UTC().Format(time.RFC3339))
// Verify there are 10 recover codes generated
var count int64
diff --git a/internal/db/users.go b/internal/db/users.go
index a002c290..64535ea3 100644
--- a/internal/db/users.go
+++ b/internal/db/users.go
@@ -9,8 +9,8 @@ import (
"strings"
"time"
- "github.com/jinzhu/gorm"
"github.com/pkg/errors"
+ "gorm.io/gorm"
"gogs.io/gogs/internal/cryptoutil"
"gogs.io/gogs/internal/errutil"
@@ -48,15 +48,19 @@ type UsersStore interface {
var Users UsersStore
// NOTE: This is a GORM create hook.
-func (u *User) BeforeCreate() {
- u.CreatedUnix = gorm.NowFunc().Unix()
- u.UpdatedUnix = u.CreatedUnix
+func (u *User) BeforeCreate(tx *gorm.DB) error {
+ if u.CreatedUnix == 0 {
+ u.CreatedUnix = tx.NowFunc().Unix()
+ u.UpdatedUnix = u.CreatedUnix
+ }
+ return nil
}
// NOTE: This is a GORM query hook.
-func (u *User) AfterFind() {
+func (u *User) AfterFind(tx *gorm.DB) error {
u.Created = time.Unix(u.CreatedUnix, 0).Local()
u.Updated = time.Unix(u.UpdatedUnix, 0).Local()
+ return nil
}
var _ UsersStore = (*users)(nil)
@@ -253,7 +257,7 @@ func (db *users) GetByEmail(email string) (*User, error) {
err := db.Where("email = ? AND type = ? AND is_active = ?", email, UserIndividual, true).First(user).Error
if err == nil {
return user, nil
- } else if !gorm.IsRecordNotFoundError(err) {
+ } else if err != gorm.ErrRecordNotFound {
return nil, err
}
@@ -261,7 +265,7 @@ func (db *users) GetByEmail(email string) (*User, error) {
emailAddress := new(EmailAddress)
err = db.Where("email = ? AND is_activated = ?", email, true).First(emailAddress).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"email": email}}
}
return nil, err
@@ -274,7 +278,7 @@ func (db *users) GetByID(id int64) (*User, error) {
user := new(User)
err := db.Where("id = ?", id).First(user).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"userID": id}}
}
return nil, err
@@ -286,7 +290,7 @@ func (db *users) GetByUsername(username string) (*User, error) {
user := new(User)
err := db.Where("lower_name = ?", strings.ToLower(username)).First(user).Error
if err != nil {
- if gorm.IsRecordNotFoundError(err) {
+ if err == gorm.ErrRecordNotFound {
return nil, ErrUserNotExist{args: errutil.Args{"name": username}}
}
return nil, err
diff --git a/internal/db/users_test.go b/internal/db/users_test.go
index 2be196e3..7ff3b9f5 100644
--- a/internal/db/users_test.go
+++ b/internal/db/users_test.go
@@ -8,7 +8,6 @@ import (
"testing"
"time"
- "github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
"gogs.io/gogs/internal/errutil"
@@ -129,8 +128,8 @@ func test_users_Create(t *testing.T, db *users) {
if err != nil {
t.Fatal(err)
}
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), user.Created.UTC().Format(time.RFC3339))
- assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), user.Updated.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), user.Created.UTC().Format(time.RFC3339))
+ assert.Equal(t, db.NowFunc().Format(time.RFC3339), user.Updated.UTC().Format(time.RFC3339))
}
func test_users_GetByEmail(t *testing.T, db *users) {
diff --git a/internal/dbutil/logger.go b/internal/dbutil/logger.go
new file mode 100644
index 00000000..66426ae7
--- /dev/null
+++ b/internal/dbutil/logger.go
@@ -0,0 +1,15 @@
+package dbutil
+
+import (
+ "fmt"
+ "io"
+)
+
+// Logger is a wrapper of io.Writer for the GORM's logger.Writer.
+type Logger struct {
+ io.Writer
+}
+
+func (l *Logger) Printf(format string, args ...interface{}) {
+ fmt.Fprintf(l.Writer, format, args...)
+}
diff --git a/internal/dbutil/writer.go b/internal/dbutil/writer.go
deleted file mode 100644
index 3b8d7363..00000000
--- a/internal/dbutil/writer.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2020 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package dbutil
-
-import (
- "fmt"
- "io"
-)
-
-// Writer is a wrapper of io.Writer for the gorm.logger.
-type Writer struct {
- io.Writer
-}
-
-func (w *Writer) Print(v ...interface{}) {
- if len(v) == 0 {
- return
- }
-
- if len(v) == 1 {
- fmt.Fprint(w.Writer, v[0])
- return
- }
-
- switch v[0] {
- case "sql":
- fmt.Fprintf(w.Writer, "[sql] [%s] [%s] %s %v (%d rows affected)", v[1:]...)
- case "log":
- fmt.Fprintf(w.Writer, "[log] [%s] %s", v[1:]...)
- case "error":
- fmt.Fprintf(w.Writer, "[err] [%s] %s", v[1:]...)
- default:
- fmt.Fprint(w.Writer, v...)
- }
-}
diff --git a/internal/dbutil/writer_test.go b/internal/dbutil/writer_test.go
deleted file mode 100644
index a484d442..00000000
--- a/internal/dbutil/writer_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2020 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package dbutil
-
-import (
- "bytes"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestWriter_Print(t *testing.T) {
- tests := []struct {
- name string
- vs []interface{}
- expOutput string
- }{
- {
- name: "no values",
- },
- {
- name: "only one value",
- vs: []interface{}{"test"},
- expOutput: "test",
- },
- {
- name: "two values",
- vs: []interface{}{"test", "output"},
- expOutput: "testoutput",
- },
-
- {
- name: "sql",
- vs: []interface{}{"sql", "writer.go:65", "1ms", "SELECT * FROM users WHERE user_id = $1", []int{1}, 1},
- expOutput: "[sql] [writer.go:65] [1ms] SELECT * FROM users WHERE user_id = $1 [1] (1 rows affected)",
- },
- {
- name: "log",
- vs: []interface{}{"log", "writer.go:65", "something"},
- expOutput: "[log] [writer.go:65] something",
- },
- {
- name: "error",
- vs: []interface{}{"error", "writer.go:65", "something bad"},
- expOutput: "[err] [writer.go:65] something bad",
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var buf bytes.Buffer
- w := &Writer{Writer: &buf}
- w.Print(test.vs...)
- assert.Equal(t, test.expOutput, buf.String())
- })
- }
-}