From fb407bcbce92f4eddc6756665dd35897edbdfd5c Mon Sep 17 00:00:00 2001 From: jolheiser Date: Fri, 16 Jun 2023 11:08:33 -0500 Subject: [PATCH 01/32] feat: non-cgo sqlite Signed-off-by: jolheiser --- go.mod | 21 ++++++++++++++--- go.sum | 55 ++++++++++++++++++++++++++++++++++--------- internal/models/db.go | 11 +++++---- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index a68dfe1..11bbacf 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,23 @@ module github.com/thomiceli/opengist go 1.19 require ( + github.com/glebarez/sqlite v1.8.0 github.com/go-playground/validator/v10 v10.11.0 github.com/google/uuid v1.3.0 github.com/gorilla/sessions v1.2.1 github.com/labstack/echo/v4 v4.10.0 github.com/markbates/goth v1.77.0 - github.com/mattn/go-sqlite3 v1.14.13 github.com/rs/zerolog v1.29.0 golang.org/x/crypto v0.2.0 golang.org/x/text v0.7.0 gopkg.in/yaml.v3 v3.0.1 - gorm.io/driver/sqlite v1.3.2 - gorm.io/gorm v1.23.5 + gorm.io/gorm v1.24.6 + modernc.org/sqlite v1.21.1 ) require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/glebarez/go-sqlite v1.21.1 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect @@ -27,16 +29,29 @@ require ( github.com/gorilla/securecookie v1.1.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/time v0.2.0 // indirect + golang.org/x/tools v0.1.12 // indirect google.golang.org/appengine v1.6.6 // indirect google.golang.org/protobuf v1.25.0 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.3 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect ) diff --git a/go.sum b/go.sum index 75daec6..407b717 100644 --- a/go.sum +++ b/go.sum @@ -47,10 +47,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= +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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -101,8 +107,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -113,6 +119,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -134,11 +141,12 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= 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.1.4/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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -171,15 +179,16 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.13 h1:1tj15ngiFfcZzii7yd82foL+ks+ouQcj8j/TPq3fk1I= -github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= @@ -247,6 +256,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -386,10 +397,11 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -481,11 +493,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/sqlite v1.3.2 h1:nWTy4cE52K6nnMhv23wLmur9Y3qWbZvOBz+V4PrGAxg= -gorm.io/driver/sqlite v1.3.2/go.mod h1:B+8GyC9K7VgzJAcrcXMRPdnMcck+8FgJynEehEPM16U= -gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gorm.io/gorm v1.23.5 h1:TnlF26wScKSvknUC/Rn8t0NLLM22fypYBlvj1+aH6dM= -gorm.io/gorm v1.23.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.24.6 h1:wy98aq9oFEetsc4CAbKD2SoBCdMzsbSIvSUUFJuHi5s= +gorm.io/gorm v1.24.6/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= 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.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -493,6 +502,30 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +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/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= +modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/models/db.go b/internal/models/db.go index a3fc124..cfd7370 100644 --- a/internal/models/db.go +++ b/internal/models/db.go @@ -2,14 +2,15 @@ package models import ( "errors" - "github.com/mattn/go-sqlite3" + "strings" + + "github.com/glebarez/sqlite" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" "github.com/thomiceli/opengist/internal/utils" - "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" - "strings" + msqlite "modernc.org/sqlite" ) var db *gorm.DB @@ -50,8 +51,8 @@ func CountAll(table interface{}) (int64, error) { } func IsUniqueConstraintViolation(err error) bool { - var sqliteErr sqlite3.Error - if errors.As(err, &sqliteErr) && sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique { + var sqliteErr *msqlite.Error + if errors.As(err, &sqliteErr) && sqliteErr.Code() == 2067 { return true } return false From af3aab21e3233cc188888e58d0fe05d558e9414d Mon Sep 17 00:00:00 2001 From: jolheiser Date: Fri, 16 Jun 2023 11:13:25 -0500 Subject: [PATCH 02/32] chore: use glebarez mirror Signed-off-by: jolheiser --- go.mod | 14 +++----------- go.sum | 24 +----------------------- internal/models/db.go | 2 +- 3 files changed, 5 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 11bbacf..be5ab58 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/thomiceli/opengist go 1.19 require ( + github.com/glebarez/go-sqlite v1.21.1 github.com/glebarez/sqlite v1.8.0 github.com/go-playground/validator/v10 v10.11.0 github.com/google/uuid v1.3.0 @@ -14,22 +15,20 @@ require ( golang.org/x/text v0.7.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/gorm v1.24.6 - modernc.org/sqlite v1.21.1 ) require ( github.com/dustin/go-humanize v1.0.1 // indirect - github.com/glebarez/go-sqlite v1.21.1 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.4.2 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -37,21 +36,14 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/time v0.2.0 // indirect - golang.org/x/tools v0.1.12 // indirect google.golang.org/appengine v1.6.6 // indirect google.golang.org/protobuf v1.25.0 // indirect - lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.40.0 // indirect - modernc.org/ccgo/v3 v3.16.13 // indirect modernc.org/libc v1.22.3 // indirect modernc.org/mathutil v1.5.0 // indirect modernc.org/memory v1.5.0 // indirect - modernc.org/opt v0.1.3 // indirect - modernc.org/strutil v1.1.3 // indirect - modernc.org/token v1.0.1 // indirect + modernc.org/sqlite v1.21.1 // indirect ) diff --git a/go.sum b/go.sum index 407b717..d555a3b 100644 --- a/go.sum +++ b/go.sum @@ -109,6 +109,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -145,8 +146,6 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -179,7 +178,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -256,8 +254,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -397,8 +393,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -502,30 +496,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= -modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= -modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= -modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= 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/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= -modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws= -modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/models/db.go b/internal/models/db.go index cfd7370..b97fd4c 100644 --- a/internal/models/db.go +++ b/internal/models/db.go @@ -4,13 +4,13 @@ import ( "errors" "strings" + msqlite "github.com/glebarez/go-sqlite" "github.com/glebarez/sqlite" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" "github.com/thomiceli/opengist/internal/utils" "gorm.io/gorm" "gorm.io/gorm/logger" - msqlite "modernc.org/sqlite" ) var db *gorm.DB From 89685bfac61f9e272ca952c19bcb3b7620781393 Mon Sep 17 00:00:00 2001 From: Thomas Miceli Date: Wed, 26 Jul 2023 10:54:16 +0200 Subject: [PATCH 03/32] Remove CONFIG env var --- internal/config/config.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index c1c3745..27dd9d2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -15,7 +15,7 @@ import ( "gopkg.in/yaml.v3" ) -var OpengistVersion = "1.4.2" +var OpengistVersion = "1.5-dev" var C *config @@ -175,17 +175,6 @@ func loadConfigFromYaml(c *config, configPath string) error { fmt.Println("No YAML config file specified.") } - // Override default values with environment variables (as yaml) - configEnv := os.Getenv("CONFIG") - if configEnv != "" { - fmt.Println("Using config from environment variable: CONFIG") - fmt.Println("!! This method of setting the config is deprecated and will be removed in a future version of Opengist") - d := yaml.NewDecoder(strings.NewReader(configEnv)) - if err := d.Decode(&c); err != nil { - return err - } - } - return nil } From b5cd49db4c4bc1f4c4c339230c2a36cb20965624 Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Wed, 26 Jul 2023 15:43:07 +0200 Subject: [PATCH 04/32] Download file, button groups, fix unknown file reading (#84) --- internal/git/commands.go | 12 ++++++++++-- internal/web/gist.go | 24 ++++++++++++++++++++++++ internal/web/run.go | 1 + public/main.ts | 2 +- templates/pages/gist.html | 28 ++++++++++++++++++++++------ 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/internal/git/commands.go b/internal/git/commands.go index b3cc687..c93b70f 100644 --- a/internal/git/commands.go +++ b/internal/git/commands.go @@ -99,9 +99,17 @@ func GetFileContent(user string, gist string, revision string, filename string, if err != nil { return "", false, err } - defer cmd.Wait() - return truncateCommandOutput(stdout, maxBytes) + output, truncated, err := truncateCommandOutput(stdout, maxBytes) + if err != nil { + return "", false, err + } + + if err := cmd.Wait(); err != nil { + return "", false, err + } + + return output, truncated, nil } func GetLog(user string, gist string, skip int) ([]*Commit, error) { diff --git a/internal/web/gist.go b/internal/web/gist.go index e3e1d67..6080fde 100644 --- a/internal/web/gist.go +++ b/internal/web/gist.go @@ -517,6 +517,30 @@ func rawFile(ctx echo.Context) error { return plainText(ctx, 200, file.Content) } +func downloadFile(ctx echo.Context) error { + gist := getData(ctx, "gist").(*models.Gist) + file, err := gist.File(ctx.Param("revision"), ctx.Param("file"), false) + + if err != nil { + return errorRes(500, "Error getting file content", err) + } + + if file == nil { + return notFound("File not found") + } + + ctx.Response().Header().Set("Content-Type", "text/plain") + ctx.Response().Header().Set("Content-Disposition", "attachment; filename="+file.Filename) + ctx.Response().Header().Set("Content-Length", strconv.Itoa(len(file.Content))) + _, err = ctx.Response().Write([]byte(file.Content)) + + if err != nil { + return errorRes(500, "Error downloading the file", err) + } + + return nil +} + func edit(ctx echo.Context) error { var gist = getData(ctx, "gist").(*models.Gist) diff --git a/internal/web/run.go b/internal/web/run.go index 0d92733..14e8b9c 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -213,6 +213,7 @@ func Start() { g3.POST("/visibility", toggleVisibility, logged, writePermission) g3.POST("/delete", deleteGist, logged, writePermission) g3.GET("/raw/:revision/:file", rawFile) + g3.GET("/download/:revision/:file", downloadFile) g3.GET("/edit", edit, logged, writePermission) g3.POST("/edit", processCreate, logged, writePermission) g3.POST("/like", like, logged) diff --git a/public/main.ts b/public/main.ts index 8992039..c354e35 100644 --- a/public/main.ts +++ b/public/main.ts @@ -178,7 +178,7 @@ document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.copy-gist-btn').forEach((e: HTMLElement) => { e.onclick = () => { - navigator.clipboard.writeText(e.parentNode!.querySelector('.gist-content')!.textContent || '').catch((err) => { + navigator.clipboard.writeText(e.parentNode!.parentNode!.querySelector('.gist-content')!.textContent || '').catch((err) => { console.error('Could not copy text: ', err); }); }; diff --git a/templates/pages/gist.html b/templates/pages/gist.html index e72cdf9..ff5932a 100644 --- a/templates/pages/gist.html +++ b/templates/pages/gist.html @@ -7,13 +7,29 @@
- - - - {{ $file.Filename }} - - Raw + + + + + {{ $file.Filename }} + + + + Raw + + + + + + + + +
{{ if $file.Truncated }} From 4f623881acc76ce9c27868d80ae7320387ac8425 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 12 Aug 2023 15:53:17 -0500 Subject: [PATCH 05/32] fix typo on admin index page (#85) --- templates/pages/admin_index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/pages/admin_index.html b/templates/pages/admin_index.html index 88bda09..27e9d69 100644 --- a/templates/pages/admin_index.html +++ b/templates/pages/admin_index.html @@ -59,13 +59,13 @@
{{ .csrfHtml }}
{{ .csrfHtml }}
From 25316d7bf2fb082063aaffa0802e000abf43b52d Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Sat, 2 Sep 2023 03:58:37 +0200 Subject: [PATCH 06/32] Added private visibility * Changed gist type and added HTML button on creation * Adapted label and edit button * Changed rules for git HTTP and SSH * Adapt Readme features --- README.md | 2 +- internal/models/gist.go | 14 +++++++------- internal/ssh/git_ssh.go | 13 +++++++++++-- internal/web/gist.go | 20 ++++++++++++++++++-- internal/web/git_http.go | 15 +++++++++++++-- internal/web/run.go | 22 ++++++++++++++++++---- public/main.ts | 16 ++++++++++++++++ templates/base/gist_header.html | 3 +-- templates/pages/all.html | 2 +- templates/pages/create.html | 21 +++++++++++++++++++-- templates/pages/edit.html | 19 +++++++++---------- 11 files changed, 114 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 30253ac..3d6a0c5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ A self-hosted pastebin **powered by Git**. [Try it here](https://opengist.thomic ## Features -* Create public or unlisted snippets +* Create public, unlisted or private snippets * Clone / Pull / Push snippets **via Git** over HTTP or SSH * Revisions history * Syntax highlighting ; markdown & CSV support diff --git a/internal/models/gist.go b/internal/models/gist.go index 3bcd1da..84e7591 100644 --- a/internal/models/gist.go +++ b/internal/models/gist.go @@ -15,7 +15,7 @@ type Gist struct { Preview string PreviewFilename string Description string - Private bool + Private int // 0: public, 1: unlisted, 2: private UserID uint User User NbFiles int @@ -89,7 +89,7 @@ func GetAllGists(offset int) ([]*Gist, error) { func GetAllGistsFromSearch(currentUserId uint, query string, offset int, sort string, order string) ([]*Gist, error) { var gists []*Gist err := db.Preload("User").Preload("Forked.User"). - Where("((gists.private = 0) or (gists.private = 1 and gists.user_id = ?))", currentUserId). + Where("((gists.private = 0) or (gists.private > 0 and gists.user_id = ?))", currentUserId). Where("gists.title like ? or gists.description like ?", "%"+query+"%", "%"+query+"%"). Limit(11). Offset(offset * 10). @@ -101,7 +101,7 @@ func GetAllGistsFromSearch(currentUserId uint, query string, offset int, sort st func gistsFromUserStatement(fromUserId uint, currentUserId uint) *gorm.DB { return db.Preload("User").Preload("Forked.User"). - Where("((gists.private = 0) or (gists.private = 1 and gists.user_id = ?))", currentUserId). + Where("((gists.private = 0) or (gists.private > 0 and gists.user_id = ?))", currentUserId). Where("users.id = ?", fromUserId). Joins("join users on gists.user_id = users.id") } @@ -124,7 +124,7 @@ func CountAllGistsFromUser(fromUserId uint, currentUserId uint) (int64, error) { func likedStatement(fromUserId uint, currentUserId uint) *gorm.DB { return db.Preload("User").Preload("Forked.User"). - Where("((gists.private = 0) or (gists.private = 1 and gists.user_id = ?))", currentUserId). + Where("((gists.private = 0) or (gists.private > 0 and gists.user_id = ?))", currentUserId). Where("likes.user_id = ?", fromUserId). Joins("join likes on gists.id = likes.gist_id"). Joins("join users on likes.user_id = users.id") @@ -147,7 +147,7 @@ func CountAllGistsLikedByUser(fromUserId uint, currentUserId uint) (int64, error func forkedStatement(fromUserId uint, currentUserId uint) *gorm.DB { return db.Preload("User").Preload("Forked.User"). - Where("gists.forked_id is not null and ((gists.private = 0) or (gists.private = 1 and gists.user_id = ?))", currentUserId). + Where("gists.forked_id is not null and ((gists.private = 0) or (gists.private > 0 and gists.user_id = ?))", currentUserId). Where("gists.user_id = ?", fromUserId). Joins("join users on gists.user_id = users.id") } @@ -243,7 +243,7 @@ func (gist *Gist) GetForks(currentUserId uint, offset int) ([]*Gist, error) { var gists []*Gist err := db.Model(&gist).Preload("User"). Where("forked_id = ?", gist.ID). - Where("(gists.private = 0) or (gists.private = 1 and gists.user_id = ?)", currentUserId). + Where("(gists.private = 0) or (gists.private > 0 and gists.user_id = ?)", currentUserId). Limit(11). Offset(offset * 10). Order("updated_at desc"). @@ -379,7 +379,7 @@ func (gist *Gist) UpdatePreviewAndCount() error { type GistDTO struct { Title string `validate:"max=50" form:"title"` Description string `validate:"max=150" form:"description"` - Private bool `form:"private"` + Private int `validate:"number,min=0,max=2" form:"private"` Files []FileDTO `validate:"min=1,dive"` } diff --git a/internal/ssh/git_ssh.go b/internal/ssh/git_ssh.go index 54ca59b..e8ade42 100644 --- a/internal/ssh/git_ssh.go +++ b/internal/ssh/git_ssh.go @@ -42,12 +42,21 @@ func runGitCommand(ch ssh.Channel, gitCmd string, key string, ip string) error { return errors.New("internal server error") } - if verb == "receive-pack" || requireLogin == "1" { + // Check for the key if : + // - user wants to push the gist + // - user wants to clone a private gist + // - gist is not found (obfuscation) + // - admin setting to require login is set to true + if verb == "receive-pack" || + gist.Private == 2 || + gist.ID == 0 || + requireLogin == "1" { + pubKey, err := models.SSHKeyExistsForUser(key, gist.UserID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Warn().Msg("Invalid SSH authentication attempt from " + ip) - return errors.New("unauthorized") + return errors.New("gist not found") } errorSsh("Failed to get user by SSH key id", err) return errors.New("internal server error") diff --git a/internal/web/gist.go b/internal/web/gist.go index 6080fde..6a44623 100644 --- a/internal/web/gist.go +++ b/internal/web/gist.go @@ -80,7 +80,7 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc { setData(ctx, "hasLiked", hasLiked) } - if gist.Private { + if gist.Private > 0 { setData(ctx, "NoIndex", true) } @@ -88,6 +88,22 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc { } } +// gistSoftInit try to load a gist (same as gistInit) but does not return a 404 if the gist is not found +// useful for git clients using HTTP to obfuscate the existence of a private gist +func gistSoftInit(next echo.HandlerFunc) echo.HandlerFunc { + return func(ctx echo.Context) error { + userName := ctx.Param("user") + gistName := ctx.Param("gistname") + + gistName = strings.TrimSuffix(gistName, ".git") + + gist, _ := models.GetGist(userName, gistName) + setData(ctx, "gist", gist) + + return next(ctx) + } +} + func allGists(ctx echo.Context) error { var err error var urlPage string @@ -400,7 +416,7 @@ func processCreate(ctx echo.Context) error { func toggleVisibility(ctx echo.Context) error { var gist = getData(ctx, "gist").(*models.Gist) - gist.Private = !gist.Private + gist.Private = (gist.Private + 1) % 3 if err := gist.Update(); err != nil { return errorRes(500, "Error updating this gist", err) } diff --git a/internal/web/git_http.go b/internal/web/git_http.go index 54e0649..61b01a0 100644 --- a/internal/web/git_http.go +++ b/internal/web/git_http.go @@ -47,16 +47,23 @@ func gitHttp(ctx echo.Context) error { gist := getData(ctx, "gist").(*models.Gist) + // Shows basic auth if : + // - user wants to push the gist + // - user wants to clone a private gist + // - gist is not found (obfuscation) + // - admin setting to require login is set to true noAuth := (ctx.QueryParam("service") == "git-upload-pack" || strings.HasSuffix(ctx.Request().URL.Path, "git-upload-pack") || ctx.Request().Method == "GET") && + gist.Private != 2 && + gist.ID != 0 && !getData(ctx, "RequireLogin").(bool) repositoryPath := git.RepositoryPath(gist.User.Username, gist.Uuid) if _, err := os.Stat(repositoryPath); os.IsNotExist(err) { if err != nil { - return errorRes(500, "Repository does not exist", err) + return errorRes(404, "Repository directory does not exist", err) } } @@ -82,12 +89,16 @@ func gitHttp(ctx echo.Context) error { return basicAuth(ctx) } + if gist.ID == 0 { + return errorRes(404, "Not found", nil) + } + if ok, err := argon2id.verify(authPassword, gist.User.Password); !ok || gist.User.Username != authUsername { if err != nil { return errorRes(500, "Cannot verify password", err) } log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP()) - return errorRes(403, "Unauthorized", nil) + return errorRes(404, "Not found", nil) } return route.handler(ctx) diff --git a/internal/web/run.go b/internal/web/run.go index 14e8b9c..3b96b28 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -30,11 +30,11 @@ var re = regexp.MustCompile("[^a-z0-9]+") var fm = template.FuncMap{ "split": strings.Split, "indexByte": strings.IndexByte, - "toInt": func(i string) int64 { - val, _ := strconv.ParseInt(i, 10, 64) + "toInt": func(i string) int { + val, _ := strconv.Atoi(i) return val }, - "inc": func(i int64) int64 { + "inc": func(i int) int { return i + 1 }, "splitGit": func(i string) []string { @@ -88,6 +88,20 @@ var fm = template.FuncMap{ return config.C.ExternalUrl + "/" + manifestEntries[jsfile].File }, "defaultAvatar": defaultAvatar, + "visibilityStr": func(visibility int, lowercase bool) string { + s := "Public" + switch visibility { + case 1: + s = "Unlisted" + case 2: + s = "Private" + } + + if lowercase { + return strings.ToLower(s) + } + return s + }, } var EmbedFS fs.FS @@ -226,7 +240,7 @@ func Start() { debugStr := "" // Git HTTP routes if config.C.HttpGit { - e.Any("/:user/:gistname/*", gitHttp, gistInit) + e.Any("/:user/:gistname/*", gitHttp, gistSoftInit) debugStr = " (with Git over HTTP)" } diff --git a/public/main.ts b/public/main.ts index c354e35..0adb138 100644 --- a/public/main.ts +++ b/public/main.ts @@ -183,4 +183,20 @@ document.addEventListener('DOMContentLoaded', () => { }); }; }); + + const gistmenuvisibility = document.getElementById('gist-menu-visibility'); + if (gistmenuvisibility) { + let submitgistbutton = (document.getElementById('submit-gist') as HTMLInputElement); + document.getElementById('gist-visibility-menu-button')!.onclick = () => { + console.log("z"); + gistmenuvisibility!.classList.toggle('hidden'); + } + Array.from(document.querySelectorAll('.gist-visibility-option')).forEach((el) => { + (el as HTMLElement).onclick = () => { + submitgistbutton.textContent = "Create " + el.textContent.toLowerCase() + " gist"; + submitgistbutton!.value = (el as HTMLElement).dataset.visibility || '0'; + gistmenuvisibility!.classList.add('hidden'); + } + }); + } }); diff --git a/templates/base/gist_header.html b/templates/base/gist_header.html index f0f5d60..cffadbe 100644 --- a/templates/base/gist_header.html +++ b/templates/base/gist_header.html @@ -92,8 +92,7 @@

Forked from {{ .gist.Forked.User.Username }}/{{ .gist.Forked.Title }}

{{ end }}

Last active {{ .gist.UpdatedAt }} - {{ if .gist.Private }} • Unlisted {{ end }} - + {{ if .gist.Private }} • {{ visibilityStr .gist.Private false }} {{ end }}

{{ .gist.Description }}

diff --git a/templates/pages/all.html b/templates/pages/all.html index 6e8402d..d5b619d 100644 --- a/templates/pages/all.html +++ b/templates/pages/all.html @@ -137,7 +137,7 @@
Last active {{ $gist.UpdatedAt }} {{ if $gist.Forked }} • Forked from {{ $gist.Forked.User.Username }}/{{ $gist.Forked.Title }} {{ end }} - {{ if $gist.Private }} • Unlisted {{ end }}
+ {{ if $gist.Private }} • {{ visibilityStr $gist.Private false }} {{ end }}
{{ $gist.Description }}
diff --git a/templates/pages/create.html b/templates/pages/create.html index a0c2169..4dc0dbc 100644 --- a/templates/pages/create.html +++ b/templates/pages/create.html @@ -56,8 +56,25 @@
- - + +
+ +
+ + +
+
{{ .csrfHtml }} diff --git a/templates/pages/edit.html b/templates/pages/edit.html index fb7f868..2aa05dd 100644 --- a/templates/pages/edit.html +++ b/templates/pages/edit.html @@ -11,18 +11,17 @@
{{ .csrfHtml }}
From a7b346d8dfc98e04ae6cf0e2257175179d8f3ab6 Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Sun, 3 Sep 2023 00:30:57 +0200 Subject: [PATCH 07/32] Tweaked project structure (#88) --- .gitattributes | 2 + Makefile | 2 +- fs_embed.go | 8 --- fs_os.go | 7 --- internal/{models => db}/admin_setting.go | 2 +- internal/{models => db}/db.go | 2 +- internal/{models => db}/gist.go | 2 +- internal/{models => db}/migration.go | 2 +- internal/{models => db}/sshkey.go | 2 +- internal/{models => db}/user.go | 2 +- internal/ssh/git_ssh.go | 10 ++-- internal/ssh/run.go | 4 +- internal/web/admin.go | 26 +++++----- internal/web/auth.go | 20 +++---- internal/web/gist.go | 66 ++++++++++++------------ internal/web/git_http.go | 8 +-- internal/web/run.go | 25 ++++----- internal/web/settings.go | 8 +-- internal/web/util.go | 8 +-- opengist.go | 6 +-- public/fs_embed.go | 8 +++ public/fs_os.go | 7 +++ public/main.ts | 5 +- public/{hljs.scss => style.scss} | 0 templates/fs_embed.go | 6 +++ 25 files changed, 122 insertions(+), 116 deletions(-) delete mode 100644 fs_embed.go delete mode 100644 fs_os.go rename internal/{models => db}/admin_setting.go (98%) rename internal/{models => db}/db.go (99%) rename internal/{models => db}/gist.go (99%) rename internal/{models => db}/migration.go (99%) rename internal/{models => db}/sshkey.go (99%) rename internal/{models => db}/user.go (99%) create mode 100644 public/fs_embed.go create mode 100644 public/fs_os.go rename public/{hljs.scss => style.scss} (100%) create mode 100644 templates/fs_embed.go diff --git a/.gitattributes b/.gitattributes index 77d15c5..bf3cf2e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,4 @@ templates/**/* linguist-vendored public/**/*.css linguist-vendored +public/**/*.scss linguist-vendored +*.config.js linguist-vendored diff --git a/Makefile b/Makefile index 447a075..bf29fb3 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Specify the name of your Go binary output BINARY_NAME := opengist -all: install build +all: clean install build install: @echo "Installing NPM dependencies..." diff --git a/fs_embed.go b/fs_embed.go deleted file mode 100644 index 30d7fd4..0000000 --- a/fs_embed.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build fs_embed - -package main - -import "embed" - -//go:embed templates/*/*.html public/manifest.json public/assets/*.js public/assets/*.css public/assets/*.svg public/assets/*.png -var dirFS embed.FS diff --git a/fs_os.go b/fs_os.go deleted file mode 100644 index a608301..0000000 --- a/fs_os.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !fs_embed - -package main - -import "os" - -var dirFS = os.DirFS(".") diff --git a/internal/models/admin_setting.go b/internal/db/admin_setting.go similarity index 98% rename from internal/models/admin_setting.go rename to internal/db/admin_setting.go index e23e938..7fb8cb4 100644 --- a/internal/models/admin_setting.go +++ b/internal/db/admin_setting.go @@ -1,4 +1,4 @@ -package models +package db import ( "gorm.io/gorm/clause" diff --git a/internal/models/db.go b/internal/db/db.go similarity index 99% rename from internal/models/db.go rename to internal/db/db.go index 8605a3c..c995e36 100644 --- a/internal/models/db.go +++ b/internal/db/db.go @@ -1,4 +1,4 @@ -package models +package db import ( "errors" diff --git a/internal/models/gist.go b/internal/db/gist.go similarity index 99% rename from internal/models/gist.go rename to internal/db/gist.go index 84e7591..9aad3da 100644 --- a/internal/models/gist.go +++ b/internal/db/gist.go @@ -1,4 +1,4 @@ -package models +package db import ( "github.com/thomiceli/opengist/internal/git" diff --git a/internal/models/migration.go b/internal/db/migration.go similarity index 99% rename from internal/models/migration.go rename to internal/db/migration.go index 3240bf0..907e2b3 100644 --- a/internal/models/migration.go +++ b/internal/db/migration.go @@ -1,4 +1,4 @@ -package models +package db import ( "fmt" diff --git a/internal/models/sshkey.go b/internal/db/sshkey.go similarity index 99% rename from internal/models/sshkey.go rename to internal/db/sshkey.go index 2dcdabc..ee62151 100644 --- a/internal/models/sshkey.go +++ b/internal/db/sshkey.go @@ -1,4 +1,4 @@ -package models +package db import ( "crypto/sha256" diff --git a/internal/models/user.go b/internal/db/user.go similarity index 99% rename from internal/models/user.go rename to internal/db/user.go index 9208d0d..f73b89b 100644 --- a/internal/models/user.go +++ b/internal/db/user.go @@ -1,4 +1,4 @@ -package models +package db import ( "gorm.io/gorm" diff --git a/internal/ssh/git_ssh.go b/internal/ssh/git_ssh.go index e8ade42..7847b17 100644 --- a/internal/ssh/git_ssh.go +++ b/internal/ssh/git_ssh.go @@ -3,8 +3,8 @@ package ssh import ( "errors" "github.com/rs/zerolog/log" + "github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/git" - "github.com/thomiceli/opengist/internal/models" "golang.org/x/crypto/ssh" "gorm.io/gorm" "io" @@ -32,12 +32,12 @@ func runGitCommand(ch ssh.Channel, gitCmd string, key string, ip string) error { userName := strings.ToLower(repoFields[0]) gistName := strings.TrimSuffix(strings.ToLower(repoFields[1]), ".git") - gist, err := models.GetGist(userName, gistName) + gist, err := db.GetGist(userName, gistName) if err != nil { return errors.New("gist not found") } - requireLogin, err := models.GetSetting(models.SettingRequireLogin) + requireLogin, err := db.GetSetting(db.SettingRequireLogin) if err != nil { return errors.New("internal server error") } @@ -52,7 +52,7 @@ func runGitCommand(ch ssh.Channel, gitCmd string, key string, ip string) error { gist.ID == 0 || requireLogin == "1" { - pubKey, err := models.SSHKeyExistsForUser(key, gist.UserID) + pubKey, err := db.SSHKeyExistsForUser(key, gist.UserID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { log.Warn().Msg("Invalid SSH authentication attempt from " + ip) @@ -61,7 +61,7 @@ func runGitCommand(ch ssh.Channel, gitCmd string, key string, ip string) error { errorSsh("Failed to get user by SSH key id", err) return errors.New("internal server error") } - _ = models.SSHKeyLastUsedNow(pubKey.Content) + _ = db.SSHKeyLastUsedNow(pubKey.Content) } repositoryPath := git.RepositoryPath(gist.User.Username, gist.Uuid) diff --git a/internal/ssh/run.go b/internal/ssh/run.go index c7d3dcd..d5c4e99 100644 --- a/internal/ssh/run.go +++ b/internal/ssh/run.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/internal/db" "golang.org/x/crypto/ssh" "gorm.io/gorm" "io" @@ -24,7 +24,7 @@ func Start() { sshConfig := &ssh.ServerConfig{ PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { strKey := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(key))) - _, err := models.SSHKeyDoesExists(strKey) + _, err := db.SSHKeyDoesExists(strKey) if err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err diff --git a/internal/web/admin.go b/internal/web/admin.go index 25d2c10..c218e13 100644 --- a/internal/web/admin.go +++ b/internal/web/admin.go @@ -4,8 +4,8 @@ import ( "github.com/labstack/echo/v4" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" + "github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/git" - "github.com/thomiceli/opengist/internal/models" "os" "path/filepath" "runtime" @@ -31,19 +31,19 @@ func adminIndex(ctx echo.Context) error { } setData(ctx, "gitVersion", gitVersion) - countUsers, err := models.CountAll(&models.User{}) + countUsers, err := db.CountAll(&db.User{}) if err != nil { return errorRes(500, "Cannot count users", err) } setData(ctx, "countUsers", countUsers) - countGists, err := models.CountAll(&models.Gist{}) + countGists, err := db.CountAll(&db.Gist{}) if err != nil { return errorRes(500, "Cannot count gists", err) } setData(ctx, "countGists", countGists) - countKeys, err := models.CountAll(&models.SSHKey{}) + countKeys, err := db.CountAll(&db.SSHKey{}) if err != nil { return errorRes(500, "Cannot count SSH keys", err) } @@ -60,9 +60,9 @@ func adminUsers(ctx echo.Context) error { setData(ctx, "adminHeaderPage", "users") pageInt := getPage(ctx) - var data []*models.User + var data []*db.User var err error - if data, err = models.GetAllUsers(pageInt - 1); err != nil { + if data, err = db.GetAllUsers(pageInt - 1); err != nil { return errorRes(500, "Cannot get users", err) } @@ -79,9 +79,9 @@ func adminGists(ctx echo.Context) error { setData(ctx, "adminHeaderPage", "gists") pageInt := getPage(ctx) - var data []*models.Gist + var data []*db.Gist var err error - if data, err = models.GetAllGists(pageInt - 1); err != nil { + if data, err = db.GetAllGists(pageInt - 1); err != nil { return errorRes(500, "Cannot get gists", err) } @@ -94,7 +94,7 @@ func adminGists(ctx echo.Context) error { func adminUserDelete(ctx echo.Context) error { userId, _ := strconv.ParseUint(ctx.Param("user"), 10, 64) - user, err := models.GetUserById(uint(userId)) + user, err := db.GetUserById(uint(userId)) if err != nil { return errorRes(500, "Cannot retrieve user", err) } @@ -108,7 +108,7 @@ func adminUserDelete(ctx echo.Context) error { } func adminGistDelete(ctx echo.Context) error { - gist, err := models.GetGistByID(ctx.Param("gist")) + gist, err := db.GetGistByID(ctx.Param("gist")) if err != nil { return errorRes(500, "Cannot retrieve gist", err) } @@ -133,7 +133,7 @@ func adminSyncReposFromFS(ctx echo.Context) error { } syncReposFromFS = true - gists, err := models.GetAllGistsRows() + gists, err := db.GetAllGistsRows() if err != nil { log.Error().Err(err).Msg("Cannot get gists") syncReposFromFS = false @@ -170,7 +170,7 @@ func adminSyncReposFromDB(ctx echo.Context) error { for _, e := range entries { path := strings.Split(e, string(os.PathSeparator)) - gist, _ := models.GetGist(path[len(path)-2], path[len(path)-1]) + gist, _ := db.GetGist(path[len(path)-2], path[len(path)-1]) if gist.ID == 0 { if err := git.DeleteRepository(path[len(path)-2], path[len(path)-1]); err != nil { @@ -197,7 +197,7 @@ func adminSetConfig(ctx echo.Context) error { key := ctx.FormValue("key") value := ctx.FormValue("value") - if err := models.UpdateSetting(key, value); err != nil { + if err := db.UpdateSetting(key, value); err != nil { return errorRes(500, "Cannot set setting", err) } diff --git a/internal/web/auth.go b/internal/web/auth.go index a5a4e9d..8af6083 100644 --- a/internal/web/auth.go +++ b/internal/web/auth.go @@ -18,7 +18,7 @@ import ( "github.com/markbates/goth/providers/github" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/internal/db" "golang.org/x/text/cases" "golang.org/x/text/language" "gorm.io/gorm" @@ -47,7 +47,7 @@ func processRegister(ctx echo.Context) error { sess := getSession(ctx) - dto := new(models.UserDTO) + dto := new(db.UserDTO) if err := ctx.Bind(dto); err != nil { return errorRes(400, "Cannot bind data", err) } @@ -57,7 +57,7 @@ func processRegister(ctx echo.Context) error { return html(ctx, "auth_form.html") } - if exists, err := models.UserExists(dto.Username); err != nil || exists { + if exists, err := db.UserExists(dto.Username); err != nil || exists { addFlash(ctx, "Username already exists", "error") return html(ctx, "auth_form.html") } @@ -101,15 +101,15 @@ func processLogin(ctx echo.Context) error { var err error sess := getSession(ctx) - dto := &models.UserDTO{} + dto := &db.UserDTO{} if err = ctx.Bind(dto); err != nil { return errorRes(400, "Cannot bind data", err) } password := dto.Password - var user *models.User + var user *db.User - if user, err = models.GetUserByUsername(dto.Username); err != nil { + if user, err = db.GetUserByUsername(dto.Username); err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { return errorRes(500, "Cannot get user", err) } @@ -161,7 +161,7 @@ func oauthCallback(ctx echo.Context) error { } // if user is not in database, create it - userDB, err := models.GetUserByProvider(user.UserID, user.Provider) + userDB, err := db.GetUserByProvider(user.UserID, user.Provider) if err != nil { if getData(ctx, "DisableSignup") == true { return errorRes(403, "Signing up is disabled", nil) @@ -171,7 +171,7 @@ func oauthCallback(ctx echo.Context) error { return errorRes(500, "Cannot get user", err) } - userDB = &models.User{ + userDB = &db.User{ Username: user.NickName, Email: user.Email, MD5Hash: fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(strings.TrimSpace(user.Email))))), @@ -188,7 +188,7 @@ func oauthCallback(ctx echo.Context) error { } if err = userDB.Create(); err != nil { - if models.IsUniqueConstraintViolation(err) { + if db.IsUniqueConstraintViolation(err) { addFlash(ctx, "Username "+user.NickName+" already exists in Opengist", "error") return redirect(ctx, "/login") } @@ -224,7 +224,7 @@ func oauthCallback(ctx echo.Context) error { keys = keys[:len(keys)-1] } for _, key := range keys { - sshKey := models.SSHKey{ + sshKey := db.SSHKey{ Title: "Added from " + user.Provider, Content: key, User: *userDB, diff --git a/internal/web/gist.go b/internal/web/gist.go index 6a44623..80c1887 100644 --- a/internal/web/gist.go +++ b/internal/web/gist.go @@ -7,7 +7,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/thomiceli/opengist/internal/config" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/internal/db" "gorm.io/gorm" "html/template" "net/url" @@ -23,7 +23,7 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc { gistName = strings.TrimSuffix(gistName, ".git") - gist, err := models.GetGist(userName, gistName) + gist, err := db.GetGist(userName, gistName) if err != nil { return notFound("Gist not found") } @@ -97,7 +97,7 @@ func gistSoftInit(next echo.HandlerFunc) echo.HandlerFunc { gistName = strings.TrimSuffix(gistName, ".git") - gist, _ := models.GetGist(userName, gistName) + gist, _ := db.GetGist(userName, gistName) setData(ctx, "gist", gist) return next(ctx) @@ -128,7 +128,7 @@ func allGists(ctx echo.Context) error { setData(ctx, "sort", sort) setData(ctx, "order", orderText) - var gists []*models.Gist + var gists []*db.Gist var currentUserId uint if userLogged != nil { currentUserId = userLogged.ID @@ -144,12 +144,12 @@ func allGists(ctx echo.Context) error { setData(ctx, "searchQuery", ctx.QueryParam("q")) setData(ctx, "searchQueryUrl", template.URL("&q="+ctx.QueryParam("q"))) urlPage = "search" - gists, err = models.GetAllGistsFromSearch(currentUserId, ctx.QueryParam("q"), pageInt-1, sort, order) + gists, err = db.GetAllGistsFromSearch(currentUserId, ctx.QueryParam("q"), pageInt-1, sort, order) } else if strings.HasSuffix(urlctx, "all") { setData(ctx, "htmlTitle", "All gists") setData(ctx, "mode", "all") urlPage = "all" - gists, err = models.GetAllGistsForCurrentUser(currentUserId, pageInt-1, sort, order) + gists, err = db.GetAllGistsForCurrentUser(currentUserId, pageInt-1, sort, order) } } else { liked := false @@ -165,9 +165,9 @@ func allGists(ctx echo.Context) error { return errorRes(500, "Error matching regexp", err) } - var fromUser *models.User + var fromUser *db.User - fromUser, err = models.GetUserByUsername(fromUserStr) + fromUser, err = db.GetUserByUsername(fromUserStr) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return notFound("User not found") @@ -176,19 +176,19 @@ func allGists(ctx echo.Context) error { } setData(ctx, "fromUser", fromUser) - if countFromUser, err := models.CountAllGistsFromUser(fromUser.ID, currentUserId); err != nil { + if countFromUser, err := db.CountAllGistsFromUser(fromUser.ID, currentUserId); err != nil { return errorRes(500, "Error counting gists", err) } else { setData(ctx, "countFromUser", countFromUser) } - if countLiked, err := models.CountAllGistsLikedByUser(fromUser.ID, currentUserId); err != nil { + if countLiked, err := db.CountAllGistsLikedByUser(fromUser.ID, currentUserId); err != nil { return errorRes(500, "Error counting liked gists", err) } else { setData(ctx, "countLiked", countLiked) } - if countForked, err := models.CountAllGistsForkedByUser(fromUser.ID, currentUserId); err != nil { + if countForked, err := db.CountAllGistsForkedByUser(fromUser.ID, currentUserId); err != nil { return errorRes(500, "Error counting forked gists", err) } else { setData(ctx, "countForked", countForked) @@ -198,17 +198,17 @@ func allGists(ctx echo.Context) error { urlPage = fromUserStr + "/liked" setData(ctx, "htmlTitle", "All gists liked by "+fromUserStr) setData(ctx, "mode", "liked") - gists, err = models.GetAllGistsLikedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order) + gists, err = db.GetAllGistsLikedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order) } else if forked { urlPage = fromUserStr + "/forked" setData(ctx, "htmlTitle", "All gists forked by "+fromUserStr) setData(ctx, "mode", "forked") - gists, err = models.GetAllGistsForkedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order) + gists, err = db.GetAllGistsForkedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order) } else { urlPage = fromUserStr setData(ctx, "htmlTitle", "All gists from "+fromUserStr) setData(ctx, "mode", "fromUser") - gists, err = models.GetAllGistsFromUser(fromUser.ID, currentUserId, pageInt-1, sort, order) + gists, err = db.GetAllGistsFromUser(fromUser.ID, currentUserId, pageInt-1, sort, order) } } @@ -225,7 +225,7 @@ func allGists(ctx echo.Context) error { } func gistIndex(ctx echo.Context) error { - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) revision := ctx.Param("revision") if revision == "" { @@ -250,7 +250,7 @@ func gistIndex(ctx echo.Context) error { } func revisions(ctx echo.Context) error { - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) userName := gist.User.Username gistName := gist.Uuid @@ -273,7 +273,7 @@ func revisions(ctx echo.Context) error { emailsSet[strings.ToLower(commit.AuthorEmail)] = struct{}{} } - emailsUsers, err := models.GetUsersFromEmails(emailsSet) + emailsUsers, err := db.GetUsersFromEmails(emailsSet) if err != nil { return errorRes(500, "Error fetching users emails", err) } @@ -302,13 +302,13 @@ func processCreate(ctx echo.Context) error { return errorRes(400, "Bad request", err) } - dto := new(models.GistDTO) - var gist *models.Gist + dto := new(db.GistDTO) + var gist *db.Gist if isCreate { setData(ctx, "htmlTitle", "Create a new gist") } else { - gist = getData(ctx, "gist").(*models.Gist) + gist = getData(ctx, "gist").(*db.Gist) setData(ctx, "htmlTitle", "Edit "+gist.Title) } @@ -316,7 +316,7 @@ func processCreate(ctx echo.Context) error { return errorRes(400, "Cannot bind data", err) } - dto.Files = make([]models.FileDTO, 0) + dto.Files = make([]db.FileDTO, 0) fileCounter := 0 for i := 0; i < len(ctx.Request().PostForm["content"]); i++ { name := ctx.Request().PostForm["name"][i] @@ -332,7 +332,7 @@ func processCreate(ctx echo.Context) error { return errorRes(400, "Invalid character unescaped", err) } - dto.Files = append(dto.Files, models.FileDTO{ + dto.Files = append(dto.Files, db.FileDTO{ Filename: strings.Trim(name, " "), Content: escapedValue, }) @@ -414,7 +414,7 @@ func processCreate(ctx echo.Context) error { } func toggleVisibility(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) gist.Private = (gist.Private + 1) % 3 if err := gist.Update(); err != nil { @@ -426,7 +426,7 @@ func toggleVisibility(ctx echo.Context) error { } func deleteGist(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) err := gist.DeleteRepository() if err != nil { @@ -442,7 +442,7 @@ func deleteGist(ctx echo.Context) error { } func like(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) currentUser := getUserLogged(ctx) hasLiked, err := currentUser.HasLiked(gist) @@ -468,7 +468,7 @@ func like(ctx echo.Context) error { } func fork(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) currentUser := getUserLogged(ctx) alreadyForked, err := gist.GetForkParent(currentUser) @@ -490,7 +490,7 @@ func fork(ctx echo.Context) error { return errorRes(500, "Error creating an UUID", err) } - newGist := &models.Gist{ + newGist := &db.Gist{ Uuid: strings.Replace(uuidGist.String(), "-", "", -1), Title: gist.Title, Preview: gist.Preview, @@ -519,7 +519,7 @@ func fork(ctx echo.Context) error { } func rawFile(ctx echo.Context) error { - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) file, err := gist.File(ctx.Param("revision"), ctx.Param("file"), false) if err != nil { @@ -534,7 +534,7 @@ func rawFile(ctx echo.Context) error { } func downloadFile(ctx echo.Context) error { - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) file, err := gist.File(ctx.Param("revision"), ctx.Param("file"), false) if err != nil { @@ -558,7 +558,7 @@ func downloadFile(ctx echo.Context) error { } func edit(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) files, err := gist.Files("HEAD") if err != nil { @@ -572,7 +572,7 @@ func edit(ctx echo.Context) error { } func downloadZip(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) var revision = ctx.Param("revision") files, err := gist.Files(revision) @@ -617,7 +617,7 @@ func downloadZip(ctx echo.Context) error { } func likes(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) pageInt := getPage(ctx) @@ -636,7 +636,7 @@ func likes(ctx echo.Context) error { } func forks(ctx echo.Context) error { - var gist = getData(ctx, "gist").(*models.Gist) + var gist = getData(ctx, "gist").(*db.Gist) pageInt := getPage(ctx) currentUser := getUserLogged(ctx) diff --git a/internal/web/git_http.go b/internal/web/git_http.go index 61b01a0..661e652 100644 --- a/internal/web/git_http.go +++ b/internal/web/git_http.go @@ -7,8 +7,8 @@ import ( "fmt" "github.com/labstack/echo/v4" "github.com/rs/zerolog/log" + "github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/git" - "github.com/thomiceli/opengist/internal/models" "net/http" "os" "os/exec" @@ -45,7 +45,7 @@ func gitHttp(ctx echo.Context) error { continue } - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) // Shows basic auth if : // - user wants to push the gist @@ -148,7 +148,7 @@ func pack(ctx echo.Context, serviceType string) error { // updatedAt is updated only if serviceType is receive-pack if serviceType == "receive-pack" { - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) _ = gist.SetLastActiveNow() _ = gist.UpdatePreviewAndCount() } @@ -159,7 +159,7 @@ func infoRefs(ctx echo.Context) error { noCacheHeaders(ctx) var service string - gist := getData(ctx, "gist").(*models.Gist) + gist := getData(ctx, "gist").(*db.Gist) serviceType := ctx.QueryParam("service") if strings.HasPrefix(serviceType, "git-") { diff --git a/internal/web/run.go b/internal/web/run.go index 3b96b28..169889a 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -10,11 +10,12 @@ import ( "github.com/markbates/goth/gothic" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" + "github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/git" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/public" + "github.com/thomiceli/opengist/templates" "html/template" "io" - "io/fs" "net/http" "os" "path/filepath" @@ -70,7 +71,7 @@ var fm = template.FuncMap{ "slug": func(s string) string { return strings.Trim(re.ReplaceAllString(strings.ToLower(s), "-"), "-") }, - "avatarUrl": func(user *models.User, noGravatar bool) string { + "avatarUrl": func(user *db.User, noGravatar bool) string { if user.AvatarURL != "" { return user.AvatarURL } @@ -104,8 +105,6 @@ var fm = template.FuncMap{ }, } -var EmbedFS fs.FS - type Template struct { templates *template.Template } @@ -118,8 +117,6 @@ func Start() { store = sessions.NewCookieStore([]byte("opengist")) gothic.Store = store - assetsFS := echo.MustSubFS(EmbedFS, "public/assets") - e := echo.New() e.HideBanner = true e.HidePort = true @@ -143,7 +140,7 @@ func Start() { e.Use(middleware.Secure()) e.Renderer = &Template{ - templates: template.Must(template.New("t").Funcs(fm).ParseFS(EmbedFS, "templates/*/*.html")), + templates: template.Must(template.New("t").Funcs(fm).ParseFS(templates.Files, "*/*.html")), } e.HTTPErrorHandler = func(er error, ctx echo.Context) { if err, ok := er.(*echo.HTTPError); ok { @@ -166,7 +163,7 @@ func Start() { if !dev { parseManifestEntries() - e.GET("/assets/*", cacheControl(echo.WrapHandler(http.StripPrefix("/assets", http.FileServer(http.FS(assetsFS)))))) + e.GET("/assets/*", cacheControl(echo.WrapHandler(http.FileServer(http.FS(public.Files))))) } // Web based routes @@ -285,9 +282,9 @@ func sessionInit(next echo.HandlerFunc) echo.HandlerFunc { sess := getSession(ctx) if sess.Values["user"] != nil { var err error - var user *models.User + var user *db.User - if user, err = models.GetUserById(sess.Values["user"].(uint)); err != nil { + if user, err = db.GetUserById(sess.Values["user"].(uint)); err != nil { sess.Values["user"] = nil saveSession(sess, ctx) setData(ctx, "userLogged", nil) @@ -315,8 +312,8 @@ func writePermission(next echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { gist := getData(ctx, "gist") user := getUserLogged(ctx) - if !gist.(*models.Gist).CanWrite(user) { - return redirect(ctx, "/"+gist.(*models.Gist).User.Username+"/"+gist.(*models.Gist).Uuid) + if !gist.(*db.Gist).CanWrite(user) { + return redirect(ctx, "/"+gist.(*db.Gist).User.Username+"/"+gist.(*db.Gist).Uuid) } return next(ctx) } @@ -377,7 +374,7 @@ type Asset struct { var manifestEntries map[string]Asset func parseManifestEntries() { - file, err := EmbedFS.Open("public/manifest.json") + file, err := public.Files.Open("manifest.json") if err != nil { log.Fatal().Err(err).Msg("Failed to open manifest.json") } diff --git a/internal/web/settings.go b/internal/web/settings.go index fd6f0d3..4056ba0 100644 --- a/internal/web/settings.go +++ b/internal/web/settings.go @@ -4,7 +4,7 @@ import ( "crypto/md5" "fmt" "github.com/labstack/echo/v4" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/internal/db" "golang.org/x/crypto/ssh" "strconv" "strings" @@ -14,7 +14,7 @@ import ( func userSettings(ctx echo.Context) error { user := getUserLogged(ctx) - keys, err := models.GetSSHKeysByUserID(user.ID) + keys, err := db.GetSSHKeysByUserID(user.ID) if err != nil { return errorRes(500, "Cannot get SSH keys", err) } @@ -61,7 +61,7 @@ func accountDeleteProcess(ctx echo.Context) error { func sshKeysProcess(ctx echo.Context) error { user := getUserLogged(ctx) - var dto = new(models.SSHKeyDTO) + var dto = new(db.SSHKeyDTO) if err := ctx.Bind(dto); err != nil { return errorRes(400, "Cannot bind data", err) } @@ -97,7 +97,7 @@ func sshKeysDelete(ctx echo.Context) error { return redirect(ctx, "/settings") } - key, err := models.GetSSHKeyByID(uint(keyId)) + key, err := db.GetSSHKeyByID(uint(keyId)) if err != nil || key.UserID != user.ID { return redirect(ctx, "/settings") diff --git a/internal/web/util.go b/internal/web/util.go index 8f6fbd2..da0e94a 100644 --- a/internal/web/util.go +++ b/internal/web/util.go @@ -11,7 +11,7 @@ import ( "github.com/gorilla/sessions" "github.com/labstack/echo/v4" "github.com/thomiceli/opengist/internal/config" - "github.com/thomiceli/opengist/internal/models" + "github.com/thomiceli/opengist/internal/db" "golang.org/x/crypto/argon2" "html/template" "net/http" @@ -60,10 +60,10 @@ func errorRes(code int, message string, err error) error { return &echo.HTTPError{Code: code, Message: message, Internal: err} } -func getUserLogged(ctx echo.Context) *models.User { +func getUserLogged(ctx echo.Context) *db.User { user := getData(ctx, "userLogged") if user != nil { - return user.(*models.User) + return user.(*db.User) } return nil } @@ -110,7 +110,7 @@ func deleteCsrfCookie(ctx echo.Context) { } func loadSettings(ctx echo.Context) error { - settings, err := models.GetSettings() + settings, err := db.GetSettings() if err != nil { return err } diff --git a/opengist.go b/opengist.go index 9bd0a9d..dbf3647 100644 --- a/opengist.go +++ b/opengist.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" + "github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/git" - "github.com/thomiceli/opengist/internal/models" "github.com/thomiceli/opengist/internal/ssh" "github.com/thomiceli/opengist/internal/web" "os" @@ -51,11 +51,9 @@ func initialize() { } log.Info().Msg("Database file: " + filepath.Join(homePath, config.C.DBFilename)) - if err := models.Setup(filepath.Join(homePath, config.C.DBFilename)); err != nil { + if err := db.Setup(filepath.Join(homePath, config.C.DBFilename)); err != nil { log.Fatal().Err(err).Msg("Failed to initialize database") } - - web.EmbedFS = dirFS } func main() { diff --git a/public/fs_embed.go b/public/fs_embed.go new file mode 100644 index 0000000..330456d --- /dev/null +++ b/public/fs_embed.go @@ -0,0 +1,8 @@ +//go:build fs_embed + +package public + +import "embed" + +//go:embed manifest.json assets/*.js assets/*.css assets/*.svg assets/*.png +var Files embed.FS diff --git a/public/fs_os.go b/public/fs_os.go new file mode 100644 index 0000000..e5ca954 --- /dev/null +++ b/public/fs_os.go @@ -0,0 +1,7 @@ +//go:build !fs_embed + +package public + +import "os" + +var Files = os.DirFS(".") diff --git a/public/main.ts b/public/main.ts index 0adb138..80d1a54 100644 --- a/public/main.ts +++ b/public/main.ts @@ -1,5 +1,5 @@ import './style.css'; -import './hljs.scss'; +import './style.scss'; import './favicon.svg'; import './default.png'; import moment from 'moment'; @@ -14,6 +14,7 @@ document.addEventListener('DOMContentLoaded', () => { e.stopPropagation() localStorage.theme = 'light'; themeMenu.classList.toggle('hidden'); + // @ts-ignore checkTheme() } @@ -21,6 +22,7 @@ document.addEventListener('DOMContentLoaded', () => { e.stopPropagation() localStorage.theme = 'dark'; themeMenu.classList.toggle('hidden'); + // @ts-ignore checkTheme() } @@ -28,6 +30,7 @@ document.addEventListener('DOMContentLoaded', () => { e.stopPropagation() localStorage.removeItem('theme'); themeMenu.classList.toggle('hidden'); + // @ts-ignore checkTheme(); } diff --git a/public/hljs.scss b/public/style.scss similarity index 100% rename from public/hljs.scss rename to public/style.scss diff --git a/templates/fs_embed.go b/templates/fs_embed.go new file mode 100644 index 0000000..b2f70ac --- /dev/null +++ b/templates/fs_embed.go @@ -0,0 +1,6 @@ +package templates + +import "embed" + +//go:embed */*.html +var Files embed.FS From ffafde2b3eee6e13463c159b1193047df0d15dab Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:11:54 +0200 Subject: [PATCH 08/32] Run git gc for repositories (#90) --- internal/git/commands.go | 42 ++++++++++++++++++++++++++++++++ internal/web/admin.go | 19 +++++++++++++++ internal/web/run.go | 1 + templates/pages/admin_index.html | 6 +++++ 4 files changed, 68 insertions(+) diff --git a/internal/git/commands.go b/internal/git/commands.go index c93b70f..57c9989 100644 --- a/internal/git/commands.go +++ b/internal/git/commands.go @@ -2,6 +2,7 @@ package git import ( "fmt" + "github.com/rs/zerolog/log" "github.com/thomiceli/opengist/internal/config" "os" "os/exec" @@ -263,6 +264,47 @@ func RPC(user string, gist string, service string) ([]byte, error) { return stdout, err } +func GcRepos() error { + subdirs, err := os.ReadDir(filepath.Join(config.GetHomeDir(), "repos")) + if err != nil { + return err + } + + for _, subdir := range subdirs { + if !subdir.IsDir() { + continue + } + + subRoot := filepath.Join(config.GetHomeDir(), "repos", subdir.Name()) + + gitRepos, err := os.ReadDir(subRoot) + if err != nil { + log.Warn().Err(err).Msg("Cannot read directory") + continue + } + + for _, repo := range gitRepos { + if !repo.IsDir() { + continue + } + + repoPath := filepath.Join(subRoot, repo.Name()) + + log.Info().Msg("Running git gc for repository " + repoPath) + + cmd := exec.Command("git", "gc") + cmd.Dir = repoPath + err = cmd.Run() + if err != nil { + log.Warn().Err(err).Msg("Cannot run git gc for repository " + repoPath) + continue + } + } + } + + return err +} + func GetGitVersion() (string, error) { cmd := exec.Command("git", "--version") stdout, err := cmd.Output() diff --git a/internal/web/admin.go b/internal/web/admin.go index c218e13..444b4a0 100644 --- a/internal/web/admin.go +++ b/internal/web/admin.go @@ -16,6 +16,7 @@ import ( var ( syncReposFromFS = false syncReposFromDB = false + gitGcRepos = false ) func adminIndex(ctx echo.Context) error { @@ -51,6 +52,7 @@ func adminIndex(ctx echo.Context) error { setData(ctx, "syncReposFromFS", syncReposFromFS) setData(ctx, "syncReposFromDB", syncReposFromDB) + setData(ctx, "gitGcRepos", gitGcRepos) return html(ctx, "admin_index.html") } @@ -185,6 +187,23 @@ func adminSyncReposFromDB(ctx echo.Context) error { return redirect(ctx, "/admin-panel") } +func adminGcRepos(ctx echo.Context) error { + addFlash(ctx, "Garbage collecting repositories...", "success") + go func() { + if gitGcRepos { + return + } + gitGcRepos = true + if err := git.GcRepos(); err != nil { + log.Error().Err(err).Msg("Error garbage collecting repositories") + gitGcRepos = false + return + } + gitGcRepos = false + }() + return redirect(ctx, "/admin-panel") +} + func adminConfig(ctx echo.Context) error { setData(ctx, "title", "Configuration") setData(ctx, "htmlTitle", "Configuration - Admin panel") diff --git a/internal/web/run.go b/internal/web/run.go index 169889a..4fb827f 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -204,6 +204,7 @@ func Start() { g2.POST("/gists/:gist/delete", adminGistDelete) g2.POST("/sync-fs", adminSyncReposFromFS) g2.POST("/sync-db", adminSyncReposFromDB) + g2.POST("/gc-repos", adminGcRepos) g2.GET("/configuration", adminConfig) g2.PUT("/set-config", adminSetConfig) } diff --git a/templates/pages/admin_index.html b/templates/pages/admin_index.html index 27e9d69..339b878 100644 --- a/templates/pages/admin_index.html +++ b/templates/pages/admin_index.html @@ -68,6 +68,12 @@ Synchronize gists from database
+
+ {{ .csrfHtml }} + +
From d4eed91130ef06d4160772e9b269f84824637b60 Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:22:09 +0200 Subject: [PATCH 09/32] Split hljs into a new file; improved dev vite server system (#91) --- internal/web/run.go | 9 ++++-- public/hljs.ts | 50 +++++++++++++++++++++++++++++++ public/main.ts | 52 ++------------------------------- templates/base/base_footer.html | 1 + templates/base/base_header.html | 11 +++++-- vite.config.js | 2 +- 6 files changed, 69 insertions(+), 56 deletions(-) create mode 100644 public/hljs.ts diff --git a/internal/web/run.go b/internal/web/run.go index 4fb827f..a4d1839 100644 --- a/internal/web/run.go +++ b/internal/web/run.go @@ -82,11 +82,14 @@ var fm = template.FuncMap{ return defaultAvatar() }, - "asset": func(jsfile string) string { + "asset": func(file string) string { if dev { - return "http://localhost:16157/" + jsfile + return "http://localhost:16157/" + file } - return config.C.ExternalUrl + "/" + manifestEntries[jsfile].File + return config.C.ExternalUrl + "/" + manifestEntries[file].File + }, + "dev": func() bool { + return dev }, "defaultAvatar": defaultAvatar, "visibilityStr": func(visibility int, lowercase bool) string { diff --git a/public/hljs.ts b/public/hljs.ts new file mode 100644 index 0000000..1edfb93 --- /dev/null +++ b/public/hljs.ts @@ -0,0 +1,50 @@ +import hljs from 'highlight.js'; +import md from 'markdown-it'; + +document.querySelectorAll('.markdown').forEach((e: HTMLElement) => { + e.innerHTML = md({ + html: true, + highlight: function (str, lang) { + if (lang && hljs.getLanguage(lang)) { + try { + return '
' +
+                        hljs.highlight(str, {language: lang, ignoreIllegals: true}).value +
+                        '
'; + } catch (__) { + } + } + + return '
' + md().utils.escapeHtml(str) + '
'; + } + }).render(e.textContent); +}); + +document.querySelectorAll('.table-code').forEach((el) => { + const ext = el.dataset.filename?.split('.').pop() || ''; + + if (hljs.autoDetection(ext) && ext !== 'txt') { + el.querySelectorAll('td.line-code').forEach((ell) => { + ell.classList.add('language-' + ext); + hljs.highlightElement(ell); + }); + } + + el.addEventListener('click', event => { + if (event.target && (event.target as HTMLElement).matches('.line-num')) { + Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected')); + + const nextSibling = (event.target as HTMLElement).nextSibling; + if (nextSibling instanceof HTMLElement) { + nextSibling.classList.add('selected'); + } + + + const filename = el.dataset.filenameSlug; + const line = (event.target as HTMLElement).textContent; + const url = location.protocol + '//' + location.host + location.pathname; + const hash = '#file-' + filename + '-' + line; + window.history.pushState(null, null, url + hash); + location.hash = hash; + } + }); +}); diff --git a/public/main.ts b/public/main.ts index 80d1a54..daacf34 100644 --- a/public/main.ts +++ b/public/main.ts @@ -34,11 +34,11 @@ document.addEventListener('DOMContentLoaded', () => { checkTheme(); } - document.getElementById('theme-btn')!.onclick = (e) => { + document.getElementById('theme-btn')!.onclick = () => { themeMenu.classList.toggle('hidden'); } - document.getElementById('user-btn')?.addEventListener("click" , (e) => { + document.getElementById('user-btn')?.addEventListener("click" , () => { document.getElementById('user-menu').classList.toggle('hidden'); }) @@ -65,53 +65,6 @@ document.addEventListener('DOMContentLoaded', () => { }; } - document.querySelectorAll('.markdown').forEach((e: HTMLElement) => { - e.innerHTML = md({ - html: true, - highlight: function (str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return '
' +
-                            hljs.highlight(str, {language: lang, ignoreIllegals: true}).value +
-                            '
'; - } catch (__) { - } - } - - return '
' + md().utils.escapeHtml(str) + '
'; - } - }).render(e.textContent); - }); - - document.querySelectorAll('.table-code').forEach((el) => { - const ext = el.dataset.filename?.split('.').pop() || ''; - - if (hljs.autoDetection(ext) && ext !== 'txt') { - el.querySelectorAll('td.line-code').forEach((ell) => { - ell.classList.add('language-' + ext); - hljs.highlightElement(ell); - }); - } - - el.addEventListener('click', event => { - if (event.target && (event.target as HTMLElement).matches('.line-num')) { - Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected')); - - const nextSibling = (event.target as HTMLElement).nextSibling; - if (nextSibling instanceof HTMLElement) { - nextSibling.classList.add('selected'); - } - - - const filename = el.dataset.filenameSlug; - const line = (event.target as HTMLElement).textContent; - const url = location.protocol + '//' + location.host + location.pathname; - const hash = '#file-' + filename + '-' + line; - window.history.pushState(null, null, url + hash); - location.hash = hash; - } - }); - }); const colorhash = () => { Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected')); @@ -191,7 +144,6 @@ document.addEventListener('DOMContentLoaded', () => { if (gistmenuvisibility) { let submitgistbutton = (document.getElementById('submit-gist') as HTMLInputElement); document.getElementById('gist-visibility-menu-button')!.onclick = () => { - console.log("z"); gistmenuvisibility!.classList.toggle('hidden'); } Array.from(document.querySelectorAll('.gist-visibility-option')).forEach((el) => { diff --git a/templates/base/base_footer.html b/templates/base/base_footer.html index b393c16..a63f90f 100644 --- a/templates/base/base_footer.html +++ b/templates/base/base_footer.html @@ -15,6 +15,7 @@

+ diff --git a/templates/base/base_header.html b/templates/base/base_header.html index 415a0c3..738d0a5 100644 --- a/templates/base/base_header.html +++ b/templates/base/base_header.html @@ -27,8 +27,15 @@ - - + + {{ if dev }} + + + + {{ else }} + + + {{ end }} {{ if .htmlTitle }} {{ .htmlTitle }} - Opengist diff --git a/vite.config.js b/vite.config.js index 454e890..7a60171 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,7 +9,7 @@ export default defineConfig({ assetsDir: 'assets', manifest: true, rollupOptions: { - input: ['./public/main.ts', './public/editor.ts', './public/admin.ts'] + input: ['./public/main.ts', './public/editor.ts', './public/admin.ts', './public/hljs.ts'] } } }) From 0d7305d9bad9ae3131bd108f1f6f1710f83932dc Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:22:24 +0200 Subject: [PATCH 10/32] Use dayjs instead of moment (#92) --- package-lock.json | 29 +++++++++++++---------------- package.json | 2 +- public/main.ts | 14 ++++++++------ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4b9764b..b389b8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,10 @@ "autoprefixer": "^10.4.14", "codemirror": "^6.0.1", "cssnano": "^5.1.15", + "dayjs": "^1.11.9", "github-markdown-css": "^5.2.0", "highlight.js": "^11.7.0", "markdown-it": "^13.0.1", - "moment": "^2.29.3", "nodemon": "^2.0.22", "postcss": "^8.4.13", "postcss-cssnext": "^3.1.1", @@ -1546,6 +1546,12 @@ "node": ">=8.0.0" } }, + "node_modules/dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==", + "dev": true + }, "node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -2380,15 +2386,6 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6114,6 +6111,12 @@ "css-tree": "^1.1.2" } }, + "dayjs": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", + "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==", + "dev": true + }, "debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -6781,12 +6784,6 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/package.json b/package.json index 0ed1af7..b4fa934 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,10 @@ "autoprefixer": "^10.4.14", "codemirror": "^6.0.1", "cssnano": "^5.1.15", + "dayjs": "^1.11.9", "github-markdown-css": "^5.2.0", "highlight.js": "^11.7.0", "markdown-it": "^13.0.1", - "moment": "^2.29.3", "nodemon": "^2.0.22", "postcss": "^8.4.13", "postcss-cssnext": "^3.1.1", diff --git a/public/main.ts b/public/main.ts index daacf34..977b108 100644 --- a/public/main.ts +++ b/public/main.ts @@ -2,10 +2,12 @@ import './style.css'; import './style.scss'; import './favicon.svg'; import './default.png'; -import moment from 'moment'; -import md from 'markdown-it'; -import hljs from 'highlight.js'; +import dayjs from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; +dayjs.extend(relativeTime); +dayjs.extend(localizedFormat); document.addEventListener('DOMContentLoaded', () => { const themeMenu = document.getElementById('theme-menu')!; @@ -43,12 +45,12 @@ document.addEventListener('DOMContentLoaded', () => { }) document.querySelectorAll('.moment-timestamp').forEach((e: HTMLElement) => { - e.title = moment.unix(parseInt(e.innerHTML)).format('LLLL'); - e.innerHTML = moment.unix(parseInt(e.innerHTML)).fromNow(); + e.title = dayjs.unix(parseInt(e.innerHTML)).format('LLLL'); + e.innerHTML = dayjs.unix(parseInt(e.innerHTML)).fromNow(); }); document.querySelectorAll('.moment-timestamp-date').forEach((e: HTMLElement) => { - e.innerHTML = moment.unix(parseInt(e.innerHTML)).format('DD/MM/YYYY HH:mm'); + e.innerHTML = dayjs.unix(parseInt(e.innerHTML)).format('DD/MM/YYYY HH:mm'); }); const rev = document.querySelector('.revision-text'); From 3e83700fc29191865fe0a405c81ca560e09ea063 Mon Sep 17 00:00:00 2001 From: Thomas Miceli <27960254+thomiceli@users.noreply.github.com> Date: Wed, 6 Sep 2023 23:36:44 +0200 Subject: [PATCH 11/32] Miscellaneous front changes (#93) * Fix fork icon * Added alt images descriptions * Add avatars next to gists links * Fix avatar for nil user * Slightly different blue primary color * Reduced main width * "New" button redirects to login when not logged in --- tailwind.config.js | 15 +++++++- templates/base/base_header.html | 8 ++-- templates/pages/all.html | 65 +++++++++++++++++++-------------- templates/pages/forks.html | 2 +- templates/pages/likes.html | 2 +- templates/pages/revisions.html | 2 +- 6 files changed, 58 insertions(+), 36 deletions(-) diff --git a/tailwind.config.js b/tailwind.config.js index c1e2b6b..a387490 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,7 +23,20 @@ module.exports = { 900: "#131316" }, rose: colors.rose, - primary: colors.sky, + primary: { + 50: '#d6e1ff', + 100: '#d1dfff', + 200: '#b9d2fe', + 300: '#84b1fb', + 400: '#74a4f6', + 500: '#588fee', + 600: '#3c79e2', + 700: '#356fc0', + 800: '#2d6195', + 900: '#2a5574', + 950: '#173040', + }, + slate: colors.slate }, extend: { diff --git a/templates/base/base_header.html b/templates/base/base_header.html index 738d0a5..938469a 100644 --- a/templates/base/base_header.html +++ b/templates/base/base_header.html @@ -47,7 +47,7 @@
@@ -136,17 +136,17 @@
{{ if .revision }} {{ if ne .revision "HEAD" }} -

Revision {{ .revision }}

+

{{ .locale.Tr "gist.header.revision" }} {{ .revision }}

{{ end }} {{ end }}
diff --git a/templates/pages/admin_config.html b/templates/pages/admin_config.html index d04432b..2234b92 100644 --- a/templates/pages/admin_config.html +++ b/templates/pages/admin_config.html @@ -3,7 +3,7 @@
-

This configuration can be overridden by a YAML config file and/or environment variables.

+

{{ .locale.Tr "admin.config-link" (join "" (toStr (.locale.Tr "admin.config-link-overriden")) "") }}