diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c0f65c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/gorm.db diff --git a/go.mod b/go.mod index 598e388..931da46 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,49 @@ module github.com/qor/transition -go 1.13 +go 1.18 require ( - github.com/jinzhu/gorm v1.9.16 + github.com/glebarez/sqlite v1.8.0 github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/qor/admin v0.0.0-20200908023436-0c0a0b041c88 github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571 github.com/qor/qor v0.0.0-20200729071734-d587cffbbb93 github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8 + gorm.io/driver/mysql v1.5.0 + gorm.io/gorm v1.25.0 +) + +require ( + github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/chris-ramon/douceur v0.2.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/glebarez/go-sqlite v1.21.1 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/context v1.1.1 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/gorilla/sessions v1.2.0 // indirect + github.com/gosimple/slug v1.9.0 // indirect + github.com/jinzhu/gorm v1.9.16 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/microcosm-cc/bluemonday v1.0.3 // indirect + github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14 // indirect + github.com/qor/middlewares v0.0.0-20170822143614-781378b69454 // indirect + github.com/qor/responder v0.0.0-20171031032654-b6def473574f // indirect + github.com/qor/session v0.0.0-20170907035918-8206b0adab70 // indirect + github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 // indirect + github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 // indirect + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/sys v0.4.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + modernc.org/libc v1.22.3 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.21.1 // indirect ) diff --git a/go.sum b/go.sum index 774c26f..e7a670b 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= @@ -6,13 +7,28 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= 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/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +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.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= +github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= +github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= +github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +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= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= @@ -29,19 +45,29 @@ github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBef 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/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +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-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= 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= github.com/microcosm-cc/bluemonday v1.0.3 h1:EjVH7OqbU219kdm8acbveoclh2zZFqPJTJw6VUlTLAQ= github.com/microcosm-cc/bluemonday v1.0.3/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= +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/qor/admin v0.0.0-20200908023436-0c0a0b041c88 h1:fMtNHN6WgFSfFZ+ZXpnJW62h4kZ+jsk1/WIsnPX9GuE= github.com/qor/admin v0.0.0-20200908023436-0c0a0b041c88/go.mod h1:TiMo/I9p4pjVFtLI8+ellx2YbeiirVYcoh5UrQc9v9I= @@ -49,9 +75,11 @@ github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14 h1:JRpyNNSRAkwNHd4WgyP github.com/qor/assetfs v0.0.0-20170713023933-ff57fdc13a14/go.mod h1:GZSCP3jIneuPsav3pXmpmJwz9ES+Fuq4ZPOUC3wwckQ= github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571 h1:87fy9oxrDUTN77K9VwHkmyNynRYl+Kn7HkX2HZbQYrE= github.com/qor/audited v0.0.0-20171228121055-b52c9c2f0571/go.mod h1:XQ/SY+Bgd2pHTAQhsSwN7KoCJSr8jJVnUqDMPk9rhYk= +github.com/qor/media v0.0.0-20200720100650-60c52edf57cb h1:LgWyG2gPmfiEukIo0yjlQ93oWWyTbmvX04rcOs4SDtk= github.com/qor/media v0.0.0-20200720100650-60c52edf57cb/go.mod h1:hzx9cTt5MpROMVIhwNhRJETc7e3a1J4bLNYflkcQ1wk= github.com/qor/middlewares v0.0.0-20170822143614-781378b69454 h1:+WCc1IigwWpWBxMFsmLUsIF230TakGHstDajd8aKDAc= github.com/qor/middlewares v0.0.0-20170822143614-781378b69454/go.mod h1:PejEyg3hS+Toh5m0AKRv2jK5br8qIoHLqmHrpg0WJYg= +github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76 h1:J2Xj92efYLxPl3BiibgEDEUiMsCBzwTurE/8JjD8CG4= github.com/qor/oss v0.0.0-20191031055114-aef9ba66bf76/go.mod h1:JhtPzUhP5KGtCB2yksmxuYAD4hEWw4qGQJpucjsm3U0= github.com/qor/qor v0.0.0-20200715033016-13227382be83/go.mod h1:oG+LgDEnsI9avcFFdczoZnBe3rw42s4cG433w6XpEig= github.com/qor/qor v0.0.0-20200729071734-d587cffbbb93 h1:kxseRCbX7NxSvKYSO1rXQCALzl3YLZvooxhhQdA23fU= @@ -61,6 +89,7 @@ github.com/qor/responder v0.0.0-20171031032654-b6def473574f/go.mod h1:0TL2G+qGDY github.com/qor/roles v0.0.0-20171127035124-d6375609fe3e/go.mod h1:++RicL9Ia/BrQHppwAsMc5CA7mAjnBLNniB46MzUteA= github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8 h1:Yv4gbXvj1JL/G4Ck4HPK7tz7gF42yntoiNINqd85NbU= github.com/qor/roles v0.0.0-20201008080147-dcaf8a4646d8/go.mod h1:++RicL9Ia/BrQHppwAsMc5CA7mAjnBLNniB46MzUteA= +github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417 h1:dnqlvo4M/uR0KhB6Tyhsv6XbSokcpfwQ4ublD9D/PBQ= github.com/qor/serializable_meta v0.0.0-20180510060738-5fd8542db417/go.mod h1:ZhRkze6qCgCNNqisHEFTAkndoBtY/XJbA03LJLJrzDY= github.com/qor/session v0.0.0-20170907035918-8206b0adab70 h1:8l21EEdlZ9R0AA3FbeUAANc5NAx8Y3tn1VKbyAgjYlI= github.com/qor/session v0.0.0-20170907035918-8206b0adab70/go.mod h1:ldgcaca0ZGx6tFtd/w0ELq5jHD/KLJ1Lbdn8qhr/pQ0= @@ -68,14 +97,22 @@ github.com/qor/validations v0.0.0-20171228122639-f364bca61b46 h1:dRlsVUhwD1pwras github.com/qor/validations v0.0.0-20171228122639-f364bca61b46/go.mod h1:UJsA0AuvrKNaWtrb1UzKai10mN3ZBbQkPjUHpxwahTc= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ= github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +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/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8 h1:di0cR5qqo2DllBMwmP75kZpUX6dAXhsn1O2dshQfMaA= github.com/theplant/cldr v0.0.0-20190423050709-9f76f7ce4ee8/go.mod h1:MIL7SmF8wRAYDn+JexczVRUiJXTCi4VbQavsCKWKwXI= +github.com/theplant/htmltestingutils v0.0.0-20190423050759-0e06de7b6967 h1:yPrgtU8bj7Q/XbXgjjmngZtOhsUufBAraruNwxv/eXM= github.com/theplant/htmltestingutils v0.0.0-20190423050759-0e06de7b6967/go.mod h1:86iN4EAYaQbx1VTW5uPslTIviRkYH8CzslMC//g+BgY= +github.com/theplant/testingutils v0.0.0-20190603093022-26d8b4d95c61 h1:757/ruZNgTsOf5EkQBo0i3Bx/P2wgF5ljVkODeUX/uA= github.com/theplant/testingutils v0.0.0-20190603093022-26d8b4d95c61/go.mod h1:p22Q3Bg5ML+hdI3QSQkB/pZ2+CjfOnGugoQIoyE2Ub8= +github.com/yosssi/gohtml v0.0.0-20200519115854-476f5b4b8047 h1:YWaOkupKL+BRRJSWRq/uhSkWXc1K0QVIYVG36XUBGOc= github.com/yosssi/gohtml v0.0.0-20200519115854-476f5b4b8047/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE= 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-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -88,4 +125,22 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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= +gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= +gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= +gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY= +modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= +modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= diff --git a/state_change_log.go b/state_change_log.go index f4a2beb..e0d3db3 100644 --- a/state_change_log.go +++ b/state_change_log.go @@ -2,9 +2,12 @@ package transition import ( "fmt" + gormv2 "gorm.io/gorm" + "gorm.io/gorm/schema" + "reflect" "strings" + "sync" - "github.com/jinzhu/gorm" "github.com/qor/admin" "github.com/qor/audited" "github.com/qor/qor/resource" @@ -13,7 +16,7 @@ import ( // StateChangeLog a model that used to keep state change logs type StateChangeLog struct { - gorm.Model + gormv2.Model ReferTable string ReferID string From string @@ -22,44 +25,81 @@ type StateChangeLog struct { audited.AuditedModel } -// GenerateReferenceKey generate reference key used for change log -func GenerateReferenceKey(model interface{}, db *gorm.DB) string { - var ( - scope = db.NewScope(model) - primaryValues []string - ) +var tableColumn = &sync.Map{} + +func getStructFieldValueByName(myStruct interface{}, columnName string) interface{} { + structValue := reflect.ValueOf(myStruct) + fieldValue := structValue.FieldByName(columnName) + return fieldValue.Interface() +} - for _, field := range scope.PrimaryFields() { - primaryValues = append(primaryValues, fmt.Sprint(field.Field.Interface())) +// GenerateReferenceKey generate reference key used for change log +func GenerateReferenceKey(model interface{}, db *gormv2.DB) (string, error) { + modelType := reflect.ValueOf(model) + for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr { + modelType = modelType.Elem() + } + if modelType.Kind() != reflect.Struct { + return "", fmt.Errorf("modelType.Kind() != reflect.Struct,%d", modelType.Kind()) + } + ss, err := schema.Parse(model, tableColumn, db.NamingStrategy) + if err != nil { + return "", err + } + var primaryValues []string + for _, field := range ss.Fields { + if field.PrimaryKey { + primaryValues = append(primaryValues, fmt.Sprintf("%v", + modelType.FieldByName(field.Name).Interface())) + } } + resStr := strings.Join(primaryValues, "::") + return resStr, nil +} - return strings.Join(primaryValues, "::") +// GenTableName table name +func GenTableName(model interface{}, db *gormv2.DB) (string, error) { + ss, err := schema.Parse(model, tableColumn, db.NamingStrategy) + if err != nil { + return "", err + } + return ss.Table, nil } // GetStateChangeLogs get state change logs -func GetStateChangeLogs(model interface{}, db *gorm.DB) []StateChangeLog { +func GetStateChangeLogs(model interface{}, db *gormv2.DB) ([]StateChangeLog, error) { var ( changelogs []StateChangeLog - scope = db.NewScope(model) ) - - db.Where("refer_table = ? AND refer_id = ?", scope.TableName(), GenerateReferenceKey(model, db)).Find(&changelogs) - - return changelogs + tableName, err := GenTableName(model, db) + if err != nil { + return nil, err + } + key, err := GenerateReferenceKey(model, db) + if err != nil { + return nil, err + } + return changelogs, db.Where("refer_table = ? AND refer_id = ?", tableName, key).Find(&changelogs).Error } // GetLastStateChange gets last state change -func GetLastStateChange(model interface{}, db *gorm.DB) *StateChangeLog { +func GetLastStateChange(model interface{}, db *gormv2.DB) (*StateChangeLog, error) { var ( changelog StateChangeLog - scope = db.NewScope(model) ) - - db.Where("refer_table = ? AND refer_id = ?", scope.TableName(), GenerateReferenceKey(model, db)).Last(&changelog) + tableName, err := GenTableName(model, db) + if err != nil { + return nil, err + } + key, err := GenerateReferenceKey(model, db) + if err != nil { + return nil, err + } + db.Where("refer_table = ? AND refer_id = ?", tableName, key).Last(&changelog) if changelog.To == "" { - return nil + return nil, nil } - return &changelog + return &changelog, nil } // ConfigureQorResource used to configure transition for qor admin diff --git a/transition.go b/transition.go index 8fd0d81..851f5d9 100644 --- a/transition.go +++ b/transition.go @@ -2,9 +2,9 @@ package transition import ( "fmt" + gormv2 "gorm.io/gorm" "strings" - "github.com/jinzhu/gorm" "github.com/qor/admin" "github.com/qor/qor/resource" "github.com/qor/roles" @@ -13,7 +13,7 @@ import ( // Transition is a struct, embed it in your struct to enable state machine for the struct type Transition struct { State string - StateChangeLogs []StateChangeLog `sql:"-"` + StateChangeLogs []StateChangeLog `sql:"-" gorm:"-"` } // SetState set state to Stater, just set, won't save it into database @@ -68,14 +68,14 @@ func (sm *StateMachine) Event(name string) *Event { } // Trigger trigger an event -func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes ...string) error { +func (sm *StateMachine) Trigger(name string, value Stater, tx *gormv2.DB, notes ...string) error { var ( - newTx *gorm.DB + newTx *gormv2.DB stateWas = value.GetState() ) if tx != nil { - newTx = tx.New() + newTx = tx.Session(&gormv2.Session{NewDB: true}) } if stateWas == "" { @@ -140,10 +140,17 @@ func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes .. } if newTx != nil { - scope := newTx.NewScope(value) + referID, err := GenerateReferenceKey(value, tx) + if err != nil { + return err + } + referTable, err := GenTableName(value, tx) + if err != nil { + return err + } log := StateChangeLog{ - ReferTable: scope.TableName(), - ReferID: GenerateReferenceKey(value, tx), + ReferTable: referTable, + ReferID: referID, From: stateWas, To: transition.to, Note: strings.Join(notes, ""), @@ -160,18 +167,18 @@ func (sm *StateMachine) Trigger(name string, value Stater, tx *gorm.DB, notes .. // State contains State information, including enter, exit hooks type State struct { Name string - enters []func(value interface{}, tx *gorm.DB) error - exits []func(value interface{}, tx *gorm.DB) error + enters []func(value interface{}, tx *gormv2.DB) error + exits []func(value interface{}, tx *gormv2.DB) error } // Enter register an enter hook for State -func (state *State) Enter(fc func(value interface{}, tx *gorm.DB) error) *State { +func (state *State) Enter(fc func(value interface{}, tx *gormv2.DB) error) *State { state.enters = append(state.enters, fc) return state } // Exit register an exit hook for State -func (state *State) Exit(fc func(value interface{}, tx *gorm.DB) error) *State { +func (state *State) Exit(fc func(value interface{}, tx *gormv2.DB) error) *State { state.exits = append(state.exits, fc) return state } @@ -193,8 +200,8 @@ func (event *Event) To(name string) *EventTransition { type EventTransition struct { to string froms []string - befores []func(value interface{}, tx *gorm.DB) error - afters []func(value interface{}, tx *gorm.DB) error + befores []func(value interface{}, tx *gormv2.DB) error + afters []func(value interface{}, tx *gormv2.DB) error } // From used to define from states @@ -204,13 +211,13 @@ func (transition *EventTransition) From(states ...string) *EventTransition { } // Before register before hooks -func (transition *EventTransition) Before(fc func(value interface{}, tx *gorm.DB) error) *EventTransition { +func (transition *EventTransition) Before(fc func(value interface{}, tx *gormv2.DB) error) *EventTransition { transition.befores = append(transition.befores, fc) return transition } // After register after hooks -func (transition *EventTransition) After(fc func(value interface{}, tx *gorm.DB) error) *EventTransition { +func (transition *EventTransition) After(fc func(value interface{}, tx *gormv2.DB) error) *EventTransition { transition.afters = append(transition.afters, fc) return transition } diff --git a/transition_test.go b/transition_test.go index 1ebd457..5a0bec0 100644 --- a/transition_test.go +++ b/transition_test.go @@ -2,31 +2,88 @@ package transition_test import ( "errors" - "testing" - - "github.com/jinzhu/gorm" + "fmt" + "github.com/glebarez/sqlite" _ "github.com/mattn/go-sqlite3" - - "github.com/qor/qor/test/utils" "github.com/qor/transition" + "gorm.io/driver/mysql" // Gorm Mysql驱动 + gormv2 "gorm.io/gorm" + "os" + "testing" ) type Order struct { - Id int + Id int `gorm:"primarykey"` Address string transition.Transition } -var db = utils.TestDB() +// TestDB initialize a db for testing +func TDB() *gormv2.DB { + var db *gormv2.DB + var err error + var dbuser, dbpwd, dbname, dbhost = "qor", "qor", "qor_test", "localhost" -func init() { - for _, model := range []interface{}{&Order{}, &transition.StateChangeLog{}} { - if err := db.DropTableIfExists(model).Error; err != nil { + if os.Getenv("DB_USER") != "" { + dbuser = os.Getenv("DB_USER") + } + + if os.Getenv("DB_PWD") != "" { + dbpwd = os.Getenv("DB_PWD") + } + + if os.Getenv("DB_NAME") != "" { + dbname = os.Getenv("DB_NAME") + } + + if os.Getenv("DB_HOST") != "" { + dbhost = os.Getenv("DB_HOST") + } + var dsn, driverName string + if os.Getenv("TEST_DB") == "postgres" { + driverName = "postgres" + dsn = fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", dbuser, dbpwd, dbhost, dbname) + } else if os.Getenv("TEST_DB") == "mysql" { + // CREATE USER 'qor'@'localhost' IDENTIFIED BY 'qor'; + // CREATE DATABASE qor_test; + // GRANT ALL ON qor_test.* TO 'qor'@'localhost'; + driverName = "mysql" + dsn = fmt.Sprintf("%s:%s@/%s?charset=utf8&parseTime=True&loc=Local", dbuser, dbpwd, dbname) + } else { + db, err = gormv2.Open(sqlite.Open("gorm.db"), &gormv2.Config{}) + if err != nil { panic(err) } + return db + } + db, err = gormv2.Open(mysql.New(mysql.Config{ + DriverName: driverName, + DSN: dsn, // data source name, refer https://github.com/go-sql-driver/mysql#dsn-data-source-name + DefaultStringSize: 255, + }), &gormv2.Config{ + CreateBatchSize: 500, // 批量写入 + SkipDefaultTransaction: false, + NamingStrategy: nil, + FullSaveAssociations: false, + }) + if err != nil { + panic(err) + } + return db +} + +var db = TDB() - if err := db.AutoMigrate(model).Error; err != nil { +func init() { + for _, model := range []interface{}{&Order{}, &transition.StateChangeLog{}} { + if ok := db.Migrator().HasTable(model); ok { + err := db.Migrator().DropTable(model) + if err != nil { + panic(err) + } + } + if err := db.AutoMigrate(model); err != nil { panic(err) } } @@ -34,7 +91,6 @@ func init() { func getStateMachine() *transition.StateMachine { var orderStateMachine = transition.New(&Order{}) - orderStateMachine.Initial("draft") orderStateMachine.State("checkout") orderStateMachine.State("paid") @@ -61,7 +117,9 @@ func CreateOrderAndExecuteTransition(transition *transition.StateMachine, event } func TestStateTransition(t *testing.T) { - order := &Order{} + order := &Order{ + Id: 1, + } if err := getStateMachine().Trigger("checkout", order, db); err != nil { t.Errorf("should not raise any error when trigger event checkout") @@ -71,7 +129,11 @@ func TestStateTransition(t *testing.T) { t.Errorf("state doesn't changed to checkout") } - var stateChangeLogs = transition.GetStateChangeLogs(order, db) + var stateChangeLogs, err = transition.GetStateChangeLogs(order, db) + if err != nil { + t.Error(err) + return + } if len(stateChangeLogs) != 1 { t.Errorf("should get one state change log with GetStateChangeLogs") } else { @@ -102,7 +164,11 @@ func TestGetLastStateChange(t *testing.T) { t.Errorf("state doesn't changed to paid") } - var lastStateChange = transition.GetLastStateChange(order, db) + var lastStateChange, err = transition.GetLastStateChange(order, db) + if err != nil { + t.Error(err) + return + } if lastStateChange.To != "paid" { t.Errorf("state to not set") } else { @@ -158,13 +224,15 @@ func TestStateCallbacks(t *testing.T) { address1 := "I'm an address should be set when enter checkout" address2 := "I'm an address should be set when exit checkout" - orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gorm.DB) error { - order.(*Order).Address = address1 - return nil - }).Exit(func(order interface{}, tx *gorm.DB) error { - order.(*Order).Address = address2 - return nil - }) + orderStateMachine.State("checkout").Enter( + func(order interface{}, tx *gormv2.DB) error { + order.(*Order).Address = address1 + return nil + }). + Exit(func(order interface{}, tx *gormv2.DB) error { + order.(*Order).Address = address2 + return nil + }) if err := orderStateMachine.Trigger("checkout", order, db); err != nil { t.Errorf("should not raise any error when trigger event checkout") @@ -190,10 +258,11 @@ func TestEventCallbacks(t *testing.T) { prevState, afterState string ) - orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gorm.DB) error { - prevState = order.(*Order).State - return nil - }).After(func(order interface{}, tx *gorm.DB) error { + orderStateMachine.Event("checkout").To("checkout").From("draft"). + Before(func(order interface{}, tx *gormv2.DB) error { + prevState = order.(*Order).State + return nil + }).After(func(order interface{}, tx *gormv2.DB) error { afterState = order.(*Order).State return nil }) @@ -218,7 +287,7 @@ func TestTransitionOnEnterCallbackError(t *testing.T) { orderStateMachine = getStateMachine() ) - orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gorm.DB) (err error) { + orderStateMachine.State("checkout").Enter(func(order interface{}, tx *gormv2.DB) (err error) { return errors.New("intentional error") }) @@ -237,7 +306,7 @@ func TestTransitionOnExitCallbackError(t *testing.T) { orderStateMachine = getStateMachine() ) - orderStateMachine.State("checkout").Exit(func(order interface{}, tx *gorm.DB) (err error) { + orderStateMachine.State("checkout").Exit(func(order interface{}, tx *gormv2.DB) (err error) { return errors.New("intentional error") }) @@ -260,7 +329,7 @@ func TestEventOnBeforeCallbackError(t *testing.T) { orderStateMachine = getStateMachine() ) - orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gorm.DB) error { + orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order interface{}, tx *gormv2.DB) error { return errors.New("intentional error") }) @@ -279,7 +348,7 @@ func TestEventOnAfterCallbackError(t *testing.T) { orderStateMachine = getStateMachine() ) - orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order interface{}, tx *gorm.DB) error { + orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order interface{}, tx *gormv2.DB) error { return errors.New("intentional error") }) @@ -291,3 +360,24 @@ func TestEventOnAfterCallbackError(t *testing.T) { t.Errorf("state transitioned on Enter callback error") } } + +type ss int + +func TestConvertInterfaceToString(t *testing.T) { + var a interface{} + a = 1 + fmt.Println(fmt.Sprintf("%v", a)) + + var b interface{} + b = 1.1 + fmt.Println(fmt.Sprintf("%v", b)) + + var d interface{} + d = "ss" + fmt.Println(fmt.Sprintf("%v", d)) + + var c interface{} + var ss = 1 + c = ss + fmt.Println(fmt.Sprintf("%v", c)) +}