diff --git a/.mockery.yaml b/.mockery.yaml
deleted file mode 100644
index f9b81680..00000000
--- a/.mockery.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-with-expecter: True
-mockname: "{{.InterfaceName}}"
-filename: "{{.MockName}}.go"
-packages:
- github.com/mraron/njudge/pkg/problems:
- interfaces:
- Judgeable:
- TaskType:
\ No newline at end of file
diff --git a/go.mod b/go.mod
index e4ee37fe..d62ab082 100644
--- a/go.mod
+++ b/go.mod
@@ -7,13 +7,13 @@ require (
github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect
github.com/friendsofgo/errors v0.9.2
github.com/gofrs/uuid v4.2.0+incompatible // indirect
- github.com/golang-jwt/jwt v3.2.2+incompatible
+ github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-migrate/migrate/v4 v4.15.1
github.com/gorilla/sessions v1.2.1
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/labstack/echo-contrib v0.12.0
- github.com/labstack/echo/v4 v4.10.0
- github.com/labstack/gommon v0.4.0 // indirect
+ github.com/labstack/echo/v4 v4.11.4
+ github.com/labstack/gommon v0.4.2 // indirect
github.com/lib/pq v1.10.6
github.com/markbates/goth v1.69.0
github.com/mattn/go-colorable v0.1.13 // indirect
@@ -26,59 +26,74 @@ require (
github.com/volatiletech/randomize v0.0.1 // indirect
github.com/volatiletech/sqlboiler/v4 v4.15.0
github.com/volatiletech/strmangle v0.0.6
- golang.org/x/crypto v0.17.0
+ golang.org/x/crypto v0.22.0
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
require (
+ github.com/a-h/templ v0.2.697
github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a
+ github.com/deepmap/oapi-codegen/v2 v2.1.0
github.com/erni27/imcache v1.2.0
- github.com/fsnotify/fsnotify v1.6.0
+ github.com/fsnotify/fsnotify v1.7.0
+ github.com/getkin/kin-openapi v0.122.0
github.com/karrick/gobls v1.3.5
+ github.com/oapi-codegen/echo-middleware v1.0.1
+ github.com/oapi-codegen/runtime v1.1.1
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b
github.com/samber/slog-echo v1.12.3
github.com/spf13/pflag v1.0.5
- github.com/stretchr/testify v1.8.4
+ github.com/stretchr/testify v1.9.0
github.com/yuin/goldmark v1.4.13
- golang.org/x/net v0.17.0
- golang.org/x/sync v0.1.0
+ golang.org/x/net v0.24.0
+ golang.org/x/sync v0.3.0
golang.org/x/text v0.14.0
- golang.org/x/time v0.2.0
+ golang.org/x/time v0.5.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/yaml.v3 v3.0.1
)
require (
+ github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ericlagergren/decimal v0.0.0-20190420051523-6335edbaa640 // indirect
+ github.com/go-openapi/jsonpointer v0.19.6 // indirect
+ github.com/go-openapi/swag v0.22.4 // indirect
github.com/golang/protobuf v1.5.2 // indirect
+ github.com/google/uuid v1.5.0 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
+ github.com/invopop/yaml v0.2.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
- github.com/pelletier/go-toml/v2 v2.0.5 // indirect
+ github.com/pelletier/go-toml/v2 v2.0.9 // indirect
+ github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
+ github.com/ugorji/go/codec v1.2.12 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/volatiletech/inflect v0.0.1 // indirect
- go.opentelemetry.io/otel v1.19.0 // indirect
- go.opentelemetry.io/otel/trace v1.19.0 // indirect
- go.uber.org/atomic v1.9.0 // indirect
+ go.opentelemetry.io/otel v1.26.0 // indirect
+ go.opentelemetry.io/otel/trace v1.26.0 // indirect
+ go.uber.org/atomic v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
- golang.org/x/mod v0.8.0 // indirect
- golang.org/x/sys v0.15.0 // indirect
- golang.org/x/tools v0.6.0 // indirect
+ golang.org/x/mod v0.17.0 // indirect
+ golang.org/x/sys v0.19.0 // indirect
+ golang.org/x/tools v0.13.0 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
diff --git a/go.sum b/go.sum
index b0604d2f..3f48f804 100644
--- a/go.sum
+++ b/go.sum
@@ -117,7 +117,12 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
+github.com/a-h/templ v0.2.680 h1:TflYFucxp5rmOxAXB9Xy3+QHTk8s8xG9+nCT/cLzjeE=
+github.com/a-h/templ v0.2.680/go.mod h1:NQGQOycaPKBxRB14DmAaeIpcGC1AOBPJEMO4ozS7m90=
+github.com/a-h/templ v0.2.697 h1:OILxtWvD0NRJaoCOiZCopRDPW8paroKlGsrAiHLykNE=
+github.com/a-h/templ v0.2.697/go.mod h1:5cqsugkq9IerRNucNsI4DEamdHPsoGMQy99DzydLhM8=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -130,6 +135,8 @@ github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a h1:dIdcLbck
github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a/go.mod h1:Sdr/tmSOLEnncCuXS5TwZRxuk7deH1WXVY8cve3eVBM=
github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY=
github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/apmckinlay/gsuneido v0.0.0-20190404155041-0b6cd442a18f/go.mod h1:JU2DOj5Fc6rol0yaT79Csr47QR0vONGwJtBNGRD7jmc=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -177,6 +184,7 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
@@ -328,6 +336,8 @@ github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjI
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/deepmap/oapi-codegen/v2 v2.1.0 h1:I/NMVhJCtuvL9x+S2QzZKpSjGi33oDZwPRdemvOZWyQ=
+github.com/deepmap/oapi-codegen/v2 v2.1.0/go.mod h1:R1wL226vc5VmCNJUvMyYr3hJMm5reyv25j952zAVXZ8=
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -391,13 +401,15 @@ github.com/friendsofgo/errors v0.9.2/go.mod h1:yCvFW5AkDIL9qn7suHVLiI/gH228n7PC4
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/getkin/kin-openapi v0.122.0 h1:WB9Jbl0Hp/T79/JF9xlSW5Kl9uYdk/AWD0yAd9HOM10=
+github.com/getkin/kin-openapi v0.122.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
@@ -419,15 +431,22 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
+github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
+github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
+github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
@@ -538,8 +557,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v35 v35.2.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -571,6 +590,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
@@ -657,6 +678,8 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
+github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
@@ -713,6 +736,8 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -723,6 +748,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
@@ -763,10 +789,10 @@ github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo-contrib v0.12.0 h1:NPr1ez+XUa5s/4LujEon+32Bxg5DO6EKSW/va06pmLc=
github.com/labstack/echo-contrib v0.12.0/go.mod h1:kR62TbwsBgmpV2HVab5iQRsQtLuhPyGqCBee88XRc4M=
-github.com/labstack/echo/v4 v4.10.0 h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=
-github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ=
-github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
-github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
+github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -782,6 +808,8 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
github.com/markbates/goth v1.69.0 h1:HoXdRES8Hfx4H4ICM27Im+IuVubflaAX7mXCmYHiWIw=
github.com/markbates/goth v1.69.0/go.mod h1:uk3KIdtCKdmyNABgOSmHFNHN0AcKqkLs8j5Ak3Ioe1Q=
@@ -795,7 +823,6 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -811,8 +838,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -852,6 +879,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@@ -870,6 +899,10 @@ github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86w
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/oapi-codegen/echo-middleware v1.0.1 h1:edYGScq1phCcuDoz9AqA9eHX+tEI1LNL5PL1lkkQh1k=
+github.com/oapi-codegen/echo-middleware v1.0.1/go.mod h1:DBQKRn+D/vfXOFbaX5GRwFttoJY64JH6yu+pdt7wU3o=
+github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
+github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -919,8 +952,11 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
+github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
+github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
+github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
+github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
@@ -1050,12 +1086,14 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ=
github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI=
+github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -1066,8 +1104,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs=
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
@@ -1080,13 +1120,14 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
+github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
@@ -1148,17 +1189,17 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
-go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
-go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
-go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
+go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
+go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
+go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
+go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
-go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
@@ -1195,8 +1236,8 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
+golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1233,6 +1274,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -1246,8 +1288,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1316,8 +1358,8 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
+golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1355,8 +1397,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1467,7 +1509,6 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1482,10 +1523,9 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
+golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1504,8 +1544,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
-golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1580,8 +1620,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/gulpfile.js b/gulpfile.js
index a217b047..ff5fe8e2 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -20,18 +20,40 @@ function mainCSS() {
safelist: {
deep: [/^modal/]
}
- })).pipe(cleanCSS({compatibility: 'ie8'})).pipe(concat('main.min.css')).pipe(dest("static/css"))
+ })).pipe(src('node_modules/select2/dist/css/select2.min.css'))
+ .pipe(src('node_modules/@ttskch/select2-bootstrap4-theme/dist/select2-bootstrap4.min.css'))
+ .pipe(cleanCSS({compatibility: 'ie8'})).pipe(concat('main.min.css')).pipe(dest("static/css"))
}
function mainJS() {
return src("src/js/*.js").pipe(dest("static/js"))
}
+function bootstrapJS() {
+ return src('node_modules/bootstrap/dist/js/bootstrap.min.js', {sourcemaps: true}).pipe(dest('static/js', {sourcemaps: '.'}))
+}
+
+function bootstrapIcons() {
+ return src('node_modules/bootstrap-icons/**/*').pipe(dest('static/bootstrap-icons'))
+}
+
+function selectJS() {
+ return src('node_modules/select2/dist/js/select2.min.js', {sourcemaps: true}).pipe(dest('static/js', {sourcemaps: '.'}))
+}
+
+function jqueryJS() {
+ return src('node_modules/jquery/dist/jquery.slim.min.js', {sourcemaps: true}).pipe(dest('static/js', {sourcemaps: '.'}))
+}
+
+function katex() {
+ return src('node_modules/katex/dist/**/*').pipe(dest('static/katex'))
+}
+
function mainFavicon() {
return src("src/favicon.ico").pipe(src("src/*.png")).pipe(src("src/site.webmanifest")).pipe(dest("static"))
}
const admin = parallel(adminCSS, adminJS)
-const main = parallel(mainCSS, mainJS, mainFavicon)
+const main = parallel(mainCSS, mainJS, mainFavicon, bootstrapJS, selectJS, jqueryJS, katex, bootstrapIcons)
exports.default = parallel(admin, main)
\ No newline at end of file
diff --git a/internal/njudge/problemlist.go b/internal/njudge/problemlist.go
index ba0655e2..db70e7fe 100644
--- a/internal/njudge/problemlist.go
+++ b/internal/njudge/problemlist.go
@@ -6,7 +6,7 @@ import (
type SortDirection string
-var (
+const (
SortASC SortDirection = "ASC"
SortDESC SortDirection = "DESC"
)
diff --git a/internal/web/env.go b/internal/web/env.go
index 1755ba74..92303c67 100644
--- a/internal/web/env.go
+++ b/internal/web/env.go
@@ -5,6 +5,7 @@ import (
"database/sql"
"fmt"
"github.com/mraron/njudge/internal/njudge/cached"
+ templates2 "github.com/mraron/njudge/internal/web/templates"
"github.com/mraron/njudge/pkg/language/langs/cpp"
"log"
"net/http"
@@ -23,7 +24,6 @@ import (
"github.com/mraron/njudge/internal/njudge/email"
"github.com/mraron/njudge/internal/njudge/memory"
"github.com/mraron/njudge/internal/web/helpers/templates"
- "github.com/mraron/njudge/internal/web/helpers/templates/partials"
"github.com/mraron/njudge/pkg/problems"
"github.com/quasoft/memstore"
"github.com/volatiletech/sqlboiler/v4/boil"
@@ -34,7 +34,7 @@ func (s *Server) SetupDataAccess() {
_ = s.ProblemStore.UpdateProblems()
if s.Mode == "demo" {
- s.PartialsStore = partials.Empty{}
+ s.PartialsStore = templates2.Empty{}
s.Categories = memory.NewCategories()
s.Tags = memory.NewTags()
@@ -79,10 +79,11 @@ func (s *Server) SetupDataAccess() {
sub.Verdict = njudge.VerdictAC
sdata, _ := prob.WithStoredData(s.ProblemStore)
ss, _ := sdata.StatusSkeleton("")
+ ss.Compiled = true
sub.Status = *ss
sub, _ = s.Submissions.Insert(context.Background(), *sub)
} else {
- s.PartialsStore = partials.NewCached(s.DB, 1*time.Minute)
+ s.PartialsStore = templates2.NewCached(s.DB, 1*time.Minute)
s.Categories = db.NewCategories(s.DB)
s.Tags = db.NewTags(s.DB)
@@ -128,7 +129,6 @@ func (s *Server) SetupEnvironment() {
}
s.SetupDataAccess()
- s.Keys.MustParse()
if s.SMTP.Enabled {
port, err := strconv.Atoi(s.SMTP.MailServerPort)
@@ -228,6 +228,9 @@ func (s *Server) setupEcho() {
s.e.Use(middleware.Logger())
s.e.Use(middleware.Recover())
s.e.Use(session.Middleware(store))
+ s.e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
+ Level: 5,
+ }))
s.prepareRoutes(s.e)
diff --git a/internal/web/handlers/api/judges.go b/internal/web/handlers/api/judges.go
index 12dd200b..10e2ab7a 100644
--- a/internal/web/handlers/api/judges.go
+++ b/internal/web/handlers/api/judges.go
@@ -3,10 +3,9 @@ package api
import (
"context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
"github.com/mraron/njudge/internal/njudge/db/models"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
-
"github.com/volatiletech/sqlboiler/v4/boil"
. "github.com/volatiletech/sqlboiler/v4/queries/qm"
)
@@ -23,7 +22,7 @@ func (JudgeDataProvider) Identifier() string {
return "id"
}
-func (dp JudgeDataProvider) List(data *pagination.Data) ([]*models.Judge, error) {
+func (dp JudgeDataProvider) List(data *templates.PaginationData) ([]*models.Judge, error) {
qms := make([]QueryMod, 0)
if data.SortField != "" {
qms = append(qms, OrderBy(data.SortField+" "+data.SortDir))
diff --git a/internal/web/handlers/api/methods.go b/internal/web/handlers/api/methods.go
index 9513a41a..ce7d2365 100644
--- a/internal/web/handlers/api/methods.go
+++ b/internal/web/handlers/api/methods.go
@@ -1,13 +1,12 @@
package api
import (
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"net/url"
"strconv"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/helpers"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
"github.com/mraron/njudge/internal/web/helpers/roles"
"github.com/labstack/echo/v4"
@@ -18,7 +17,7 @@ type Provider[T any] interface {
Identifier() string
- List(*pagination.Data) ([]*T, error)
+ List(*templates.PaginationData) ([]*T, error)
Count() (int64, error)
Get(string) (*T, error)
}
@@ -36,10 +35,10 @@ func GetList[T any](dp Provider[T]) echo.HandlerFunc {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionView, roles.Entity(dp.EndpointURL())) {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
- data, err := pagination.Parse(c)
+ data, err := templates.ParsePaginationData(c)
if err != nil {
return err
}
@@ -67,7 +66,7 @@ func Get[T any](dp Provider[T]) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionView, roles.Entity(dp.EndpointURL())) {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
id, err := url.QueryUnescape(c.Param(dp.Identifier()))
@@ -88,7 +87,7 @@ func Post[T any](dp WritableProvider[T]) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionCreate, roles.Entity(dp.EndpointURL())) {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
elem := new(T)
@@ -108,7 +107,7 @@ func Put[T any](dp WritableProvider[T]) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionEdit, roles.Entity(dp.EndpointURL())) {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
id, err := url.QueryUnescape(c.Param(dp.Identifier()))
@@ -136,7 +135,7 @@ func Delete[T any](dp WritableProvider[T]) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionDelete, roles.Entity(dp.EndpointURL())) {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
id, err := url.QueryUnescape(c.Param(dp.Identifier()))
diff --git a/internal/web/handlers/api/partials.go b/internal/web/handlers/api/partials.go
index 257d5ff3..265b6625 100644
--- a/internal/web/handlers/api/partials.go
+++ b/internal/web/handlers/api/partials.go
@@ -3,10 +3,9 @@ package api
import (
"context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
"github.com/mraron/njudge/internal/njudge/db/models"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
-
"github.com/volatiletech/sqlboiler/v4/boil"
. "github.com/volatiletech/sqlboiler/v4/queries/qm"
)
@@ -23,7 +22,7 @@ func (PartialDataProvider) Identifier() string {
return "name"
}
-func (dp PartialDataProvider) List(data *pagination.Data) ([]*models.Partial, error) {
+func (dp PartialDataProvider) List(data *templates.PaginationData) ([]*models.Partial, error) {
qms := make([]QueryMod, 0)
if data.SortField != "" {
qms = append(qms, OrderBy("name "+data.SortDir))
diff --git a/internal/web/handlers/api/problem_rels.go b/internal/web/handlers/api/problem_rels.go
index e2c3d246..cdec4e0b 100644
--- a/internal/web/handlers/api/problem_rels.go
+++ b/internal/web/handlers/api/problem_rels.go
@@ -3,11 +3,10 @@ package api
import (
"context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
"strconv"
"github.com/mraron/njudge/internal/njudge/db/models"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
-
"github.com/volatiletech/sqlboiler/v4/boil"
. "github.com/volatiletech/sqlboiler/v4/queries/qm"
)
@@ -24,7 +23,7 @@ func (ProblemRelDataProvider) Identifier() string {
return "id"
}
-func (dp ProblemRelDataProvider) List(data *pagination.Data) ([]*models.ProblemRel, error) {
+func (dp ProblemRelDataProvider) List(data *templates.PaginationData) ([]*models.ProblemRel, error) {
qms := make([]QueryMod, 0)
if data.SortField != "" {
qms = append(qms, OrderBy(data.SortField+" "+data.SortDir))
diff --git a/internal/web/handlers/api/submissions.go b/internal/web/handlers/api/submissions.go
index 7b0fed4b..04103378 100644
--- a/internal/web/handlers/api/submissions.go
+++ b/internal/web/handlers/api/submissions.go
@@ -3,11 +3,10 @@ package api
import (
"context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
"strconv"
"github.com/mraron/njudge/internal/njudge/db/models"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
-
"github.com/volatiletech/sqlboiler/v4/boil"
. "github.com/volatiletech/sqlboiler/v4/queries/qm"
)
@@ -24,7 +23,7 @@ func (SubmissionDataProvider) Identifier() string {
return "id"
}
-func (dp SubmissionDataProvider) List(data *pagination.Data) ([]*models.Submission, error) {
+func (dp SubmissionDataProvider) List(data *templates.PaginationData) ([]*models.Submission, error) {
qms := make([]QueryMod, 0)
if data.SortField != "" {
qms = append(qms, OrderBy(data.SortField+" "+data.SortDir))
diff --git a/internal/web/handlers/api/users.go b/internal/web/handlers/api/users.go
index b28e6e81..48649bb9 100644
--- a/internal/web/handlers/api/users.go
+++ b/internal/web/handlers/api/users.go
@@ -3,12 +3,11 @@ package api
import (
"context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
"strconv"
"github.com/mraron/njudge/internal/njudge/db/models"
"github.com/mraron/njudge/internal/web/helpers"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
-
"github.com/volatiletech/sqlboiler/v4/boil"
. "github.com/volatiletech/sqlboiler/v4/queries/qm"
)
@@ -25,7 +24,7 @@ func (UserDataProvider) Identifier() string {
return "id"
}
-func (dp UserDataProvider) List(data *pagination.Data) ([]*models.User, error) {
+func (dp UserDataProvider) List(data *templates.PaginationData) ([]*models.User, error) {
qms := make([]QueryMod, 0)
if data.SortField != "" {
qms = append(qms, OrderBy(data.SortField+" "+data.SortDir))
diff --git a/internal/web/handlers/pages.go b/internal/web/handlers/pages.go
index 016a0314..fc14b317 100644
--- a/internal/web/handlers/pages.go
+++ b/internal/web/handlers/pages.go
@@ -1,36 +1,35 @@
package handlers
import (
+ "github.com/mraron/njudge/internal/web/templates"
"html/template"
"net/http"
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/helpers/config"
"github.com/mraron/njudge/internal/web/helpers/roles"
- "github.com/mraron/njudge/internal/web/helpers/templates/partials"
)
-func GetHome() echo.HandlerFunc {
+func GetHome(store templates.Store) echo.HandlerFunc {
return func(c echo.Context) error {
- return c.Render(http.StatusOK, "home.gohtml", nil)
+ c.Set(templates.TitleContextKey, "")
+ res, _ := store.Get("home")
+ return templates.Render(c, http.StatusOK, templates.Home(res))
}
}
-func GetAdmin(cfg config.Server) echo.HandlerFunc {
+func GetAdmin() echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionView, "admin_panel") {
- return c.Render(http.StatusUnauthorized, "error.gohtml", "Engedély megtagadva.")
+ return echo.NotFoundHandler(c)
}
- return c.Render(http.StatusOK, "admin.gohtml", struct {
- Url string
- }{cfg.Url})
+ return templates.Render(c, http.StatusOK, templates.Admin())
}
}
-func GetPage(store partials.Store) echo.HandlerFunc {
+func GetPage(store templates.Store) echo.HandlerFunc {
return func(c echo.Context) error {
contents, err := store.Get("page_" + c.Param("page"))
if err != nil {
diff --git a/internal/web/handlers/problemset/problem.go b/internal/web/handlers/problemset/problem.go
index 8c8fec83..bb848ec8 100644
--- a/internal/web/handlers/problemset/problem.go
+++ b/internal/web/handlers/problemset/problem.go
@@ -3,6 +3,7 @@ package problemset
import (
"bytes"
"errors"
+ "github.com/mraron/njudge/internal/web/templates"
"io"
"mime"
"net/http"
@@ -11,9 +12,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/i18n"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
"github.com/mraron/njudge/pkg/problems"
)
@@ -22,26 +21,26 @@ func GetProblem() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
prob := c.Get("problem").(njudge.Problem)
info := c.Get("problemInfo").(njudge.ProblemInfo)
- sdata := c.Get("problemStoredData").(njudge.ProblemStoredData)
+ storedData := c.Get("problemStoredData").(njudge.ProblemStoredData)
c.Set("title", tr.Translate("Statement - %s (%s)",
- tr.TranslateContent(sdata.Titles()).String(), sdata.Name()))
+ tr.TranslateContent(storedData.Titles()).String(), storedData.Name()))
return c.Render(http.StatusOK, "problemset/problem/problem", struct {
njudge.Problem
njudge.ProblemStoredData
njudge.ProblemInfo
- }{Problem: prob, ProblemStoredData: sdata, ProblemInfo: info})
+ }{Problem: prob, ProblemStoredData: storedData, ProblemInfo: info})
}
}
func GetProblemPDF() echo.HandlerFunc {
return func(c echo.Context) error {
- sdata := c.Get("problemStoredData").(njudge.ProblemStoredData)
+ storedData := c.Get("problemStoredData").(njudge.ProblemStoredData)
lang := c.Param("language")
- r, err := sdata.GetPDF(njudge.Language(lang))
+ r, err := storedData.GetPDF(njudge.Language(lang))
if err != nil {
return err
}
@@ -57,9 +56,9 @@ func GetProblemPDF() echo.HandlerFunc {
func GetProblemFile() echo.HandlerFunc {
return func(c echo.Context) error {
- sdata := c.Get("problemStoredData").(njudge.ProblemStoredData)
+ storedData := c.Get("problemStoredData").(njudge.ProblemStoredData)
- fileLoc, err := sdata.GetFile(c.Param("file"))
+ fileLoc, err := storedData.GetFile(c.Param("file"))
if errors.Is(err, njudge.ErrorFileNotFound) {
return echo.NewHTTPError(http.StatusNotFound, err)
} else if err != nil {
@@ -72,10 +71,10 @@ func GetProblemFile() echo.HandlerFunc {
func GetProblemAttachment() echo.HandlerFunc {
return func(c echo.Context) error {
- sdata := c.Get("problemStoredData").(njudge.ProblemStoredData)
+ storedData := c.Get("problemStoredData").(njudge.ProblemStoredData)
attachment := c.Param("attachment")
- val, err := sdata.GetAttachment(attachment)
+ val, err := storedData.GetAttachment(attachment)
if errors.Is(err, njudge.ErrorFileNotFound) {
return echo.NewHTTPError(http.StatusNotFound, err)
} else if err != nil {
@@ -100,15 +99,15 @@ func GetProblemAttachment() echo.HandlerFunc {
}
}
-func GetProblemRanklist(slist njudge.SubmissionListQuery) echo.HandlerFunc {
+func GetProblemRanklist(subList njudge.SubmissionListQuery) echo.HandlerFunc {
return func(c echo.Context) error {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
problemset, problemName := c.Param("name"), c.Param("problem")
prob := c.Get("problem").(njudge.Problem)
- sdata := c.Get("problemStoredData").(njudge.ProblemStoredData)
+ storedData := c.Get("problemStoredData").(njudge.ProblemStoredData)
- submissions, err := slist.GetSubmissionList(c.Request().Context(), njudge.SubmissionListRequest{
+ submissions, err := subList.GetSubmissionList(c.Request().Context(), njudge.SubmissionListRequest{
Problemset: problemset,
Problem: problemName,
SortDir: njudge.SortDESC,
@@ -129,12 +128,12 @@ func GetProblemRanklist(slist njudge.SubmissionListQuery) echo.HandlerFunc {
hadUser[submissions.Submissions[ind].UserID] = true
}
- c.Set("title", tr.Translate("Results - %s (%s)", tr.TranslateContent(sdata.Titles()).String(), sdata.Name()))
+ c.Set("title", tr.Translate("Results - %s (%s)", tr.TranslateContent(storedData.Titles()).String(), storedData.Name()))
return c.Render(http.StatusOK, "problemset/problem/ranklist", struct {
Problem njudge.Problem
ProblemStoredData njudge.ProblemStoredData
Submissions []njudge.Submission
- }{prob, sdata, res})
+ }{prob, storedData, res})
}
}
@@ -155,7 +154,7 @@ func GetProblemSubmit() echo.HandlerFunc {
}
}
-func GetProblemStatus(slist njudge.SubmissionListQuery, pstore problems.Store) echo.HandlerFunc {
+func GetProblemStatus(subList njudge.SubmissionListQuery, probList problems.Store) echo.HandlerFunc {
type request struct {
AC string `query:"ac"`
UserID int `query:"user_id"`
@@ -168,7 +167,7 @@ func GetProblemStatus(slist njudge.SubmissionListQuery, pstore problems.Store) e
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
prob := c.Get("problem").(njudge.Problem)
- sdata, err := prob.WithStoredData(pstore)
+ storedData, err := prob.WithStoredData(probList)
if err != nil {
return err
}
@@ -200,23 +199,23 @@ func GetProblemStatus(slist njudge.SubmissionListQuery, pstore problems.Store) e
statusReq.Verdict = &ac
}
- submissionList, err := slist.GetPagedSubmissionList(c.Request().Context(), statusReq)
+ submissionList, err := subList.GetPagedSubmissionList(c.Request().Context(), statusReq)
if err != nil {
return err
}
qu := (*c.Request().URL).Query()
- links, err := pagination.LinksWithCountLimit(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu, 5)
+ links, err := templates.LinksWithCountLimit(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu, 5)
if err != nil {
return err
}
- result := StatusPage{
+ result := templates.SubmissionsViewModel{
Submissions: submissionList.Submissions,
Pages: links,
}
- c.Set("title", tr.Translate("Submissions - %s (%s)", tr.TranslateContent(sdata.Titles()).String(), sdata.Name()))
+ c.Set("title", tr.Translate("Submissions - %s (%s)", tr.TranslateContent(storedData.Titles()).String(), storedData.Name()))
return c.Render(http.StatusOK, "problemset/problem/status", result)
}
}
@@ -233,7 +232,7 @@ func PostProblemTag(tgs njudge.TagsService) echo.HandlerFunc {
u := c.Get("user").(*njudge.User)
if u == nil {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
pr := c.Get("problem").(njudge.Problem)
@@ -257,7 +256,7 @@ func DeleteProblemTag(tgs njudge.TagsService) echo.HandlerFunc {
u := c.Get("user").(*njudge.User)
if u == nil {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
pr := c.Get("problem").(njudge.Problem)
diff --git a/internal/web/handlers/problemset/problemset.go b/internal/web/handlers/problemset/problemset.go
index 7bcf473e..3df3867a 100644
--- a/internal/web/handlers/problemset/problemset.go
+++ b/internal/web/handlers/problemset/problemset.go
@@ -2,6 +2,8 @@ package problemset
import (
"fmt"
+ "github.com/a-h/templ"
+ "github.com/mraron/njudge/internal/web/templates"
"io"
"net/http"
"sort"
@@ -11,67 +13,50 @@ import (
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
"github.com/mraron/njudge/internal/web/helpers/i18n"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
- "github.com/mraron/njudge/internal/web/helpers/ui"
"github.com/mraron/njudge/pkg/problems"
)
-type CategoryFilterOption struct {
- Name string
- Value string
- Selected bool
-}
+type ProblemListRequest struct {
+ Page int `query:"page"`
+ Order_ string `query:"order"`
+ Order njudge.SortDirection
+ By_ string `query:"by"`
+ By njudge.ProblemSortField
-type Problem struct {
- njudge.Problem
- njudge.ProblemStoredData
- njudge.ProblemInfo
+ TitleFilter string `query:"title"`
+ CategoryFilter int `query:"category"`
+ TagFilter string `query:"tags"`
- CategoryLink ui.Link
+ Problemset string `param:"name"`
}
-type ProblemList struct {
- Pages []pagination.Link
- Problems []Problem
- SolverSorter ui.SortColumn
-
- Filtered bool
+func NewProblemListRequest(c echo.Context) (*ProblemListRequest, error) {
+ data := ProblemListRequest{}
+ if err := c.Bind(&data); err != nil {
+ return nil, err
+ }
+ if data.Page <= 0 {
+ data.Page = 1
+ }
- TitleFilter string
- TagsFilter string
- CategoryFilterOptions []CategoryFilterOption
+ data.Order, data.By = njudge.SortDESC, njudge.ProblemSortFieldID
+ if c.QueryParam("by") == "solver_count" {
+ data.By = njudge.ProblemSortFieldSolverCount
+ }
+ if c.QueryParam("order") == "ASC" {
+ data.Order = njudge.SortASC
+ }
+ return &data, nil
}
-func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categories, problemListQuery njudge.ProblemListQuery, pinfo njudge.ProblemInfoQuery) echo.HandlerFunc {
- type request struct {
- Page int `query:"page"`
- Order njudge.SortDirection
- By njudge.ProblemSortField
-
- TitleFilter string `query:"title"`
- CategoryFilter int `query:"category"`
- TagFilter string `query:"tags"`
+func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categories, problemListQuery njudge.ProblemListQuery, pinfo njudge.ProblemInfoQuery, tags njudge.Tags) echo.HandlerFunc {
- Problemset string `param:"name"`
- }
return func(c echo.Context) error {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
-
- data := request{}
- if err := c.Bind(&data); err != nil {
+ data, err := NewProblemListRequest(c)
+ if err != nil {
return err
}
- if data.Page <= 0 {
- data.Page = 1
- }
-
- data.Order, data.By = njudge.SortDESC, njudge.ProblemSortFieldID
- if c.QueryParam("by") == "solver_count" {
- data.By = njudge.ProblemSortFieldSolverCount
- }
- if c.QueryParam("order") == "ASC" {
- data.Order = njudge.SortASC
- }
listRequest := njudge.ProblemListRequest{
Problemset: data.Problemset,
@@ -101,12 +86,44 @@ func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categori
}
u := *c.Request().URL
- links, err := pagination.Links(problemList.PaginationData.Page, problemList.PaginationData.PerPage, int64(problemList.PaginationData.Count), u.Query())
+ links, err := templates.Links(problemList.PaginationData.Page, problemList.PaginationData.PerPage, int64(problemList.PaginationData.Count), u.Query())
+ if err != nil {
+ return err
+ }
+
+ tagsList, err := tags.GetAll(c.Request().Context())
if err != nil {
return err
}
- result := ProblemList{
+ result := templates.ProblemListViewModel{
Pages: links,
+ Tags: tagsList,
+ }
+
+ categories, err := cs.GetAll(c.Request().Context())
+ if err != nil {
+ return err
+ }
+
+ par := make(map[int]int)
+ for ind := range categories {
+ if categories[ind].ParentID.Valid {
+ par[categories[ind].ID] = categories[ind].ParentID.Int
+ }
+ }
+
+ categoryNameByID := make(map[int]string)
+ for ind := range categories {
+ categoryNameByID[categories[ind].ID] = categories[ind].Name
+ }
+
+ var getCategoryNameRec func(int) string
+ getCategoryNameRec = func(id int) string {
+ if _, ok := par[id]; !ok {
+ return categoryNameByID[id]
+ } else {
+ return getCategoryNameRec(par[id]) + " -- " + categoryNameByID[id]
+ }
}
for ind := range problemList.Problems {
@@ -123,17 +140,48 @@ func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categori
return err
}
- result.Problems = append(result.Problems, Problem{
- Problem: *p,
- ProblemInfo: *info,
- ProblemStoredData: data,
- })
+ curr := templates.ProblemListProblem{
+ Name: p.Problem,
+ Titles: data.Titles(),
+ Visible: p.Visible,
+ UserInfo: info.UserInfo,
+ ShowTags: true,
+ Tags: nil,
+ SolverCount: p.SolverCount,
+ }
+
+ for _, tag := range p.Tags {
+ curr.Tags = append(curr.Tags, tag.Tag)
+ }
+
+ if u := c.Get(templates.UserContextKey).(*njudge.User); u != nil {
+ if info.UserInfo.SolvedStatus != njudge.Solved && !u.Settings.ShowUnsolvedTags {
+ curr.ShowTags = false
+ }
+ }
+
+ if p.Category != nil {
+ cid := p.Category.ID
+ for {
+ if _, ok := par[cid]; ok {
+ cid = par[cid]
+ } else {
+ break
+ }
+ }
+
+ curr.CategoryLink = templates.Link{
+ Text: categoryNameByID[cid],
+ Href: templ.SafeURL(fmt.Sprintf("/task_archive#category%d", p.Category.ID)),
+ }
+ }
+
+ result.Problems = append(result.Problems, curr)
}
- sortOrder, u := "", *c.Request().URL
+ u = *c.Request().URL
qu := u.Query()
- if qu.Get("by") == "solver_count" {
- sortOrder = qu.Get("order")
+ if data.By == njudge.ProblemSortFieldSolverCount {
if qu.Get("order") == "DESC" {
qu.Set("order", "ASC")
} else {
@@ -144,15 +192,15 @@ func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categori
qu.Set("by", "solver_count")
qu.Set("order", "DESC")
}
- result.SolverSorter = ui.SortColumn{
- Order: sortOrder,
+ result.SolverSorter = templates.SortColumn{
+ Order: data.Order,
Href: "?" + qu.Encode(),
}
result.Filtered = listRequest.IsFiltered()
result.TitleFilter = data.TitleFilter
result.TagsFilter = data.TagFilter
- result.CategoryFilterOptions = []CategoryFilterOption{
+ result.CategoryFilterOptions = []templates.CategoryFilterOption{
{Name: "-"},
}
@@ -160,40 +208,14 @@ func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categori
if data.CategoryFilter == -1 {
emptySelected = true
}
- result.CategoryFilterOptions = append(result.CategoryFilterOptions, CategoryFilterOption{
+ result.CategoryFilterOptions = append(result.CategoryFilterOptions, templates.CategoryFilterOption{
Name: tr.Translate("No category"),
Value: "-1",
Selected: emptySelected,
})
- categories, err := cs.GetAll(c.Request().Context())
- if err != nil {
- return err
- }
-
- par := make(map[int]int)
- for ind := range categories {
- if categories[ind].ParentID.Valid {
- par[categories[ind].ID] = categories[ind].ParentID.Int
- }
- }
-
- categoryNameByID := make(map[int]string)
for ind := range categories {
- categoryNameByID[categories[ind].ID] = categories[ind].Name
- }
-
- var getCategoryNameRec func(int) string
- getCategoryNameRec = func(id int) string {
- if _, ok := par[id]; !ok {
- return categoryNameByID[id]
- } else {
- return getCategoryNameRec(par[id]) + " -- " + categoryNameByID[id]
- }
- }
-
- for ind := range categories {
- curr := CategoryFilterOption{
+ curr := templates.CategoryFilterOption{
Name: getCategoryNameRec(categories[ind].ID),
Value: strconv.Itoa(categories[ind].ID),
Selected: false,
@@ -210,46 +232,24 @@ func GetProblemList(store problems.Store, ps njudge.Problems, cs njudge.Categori
return result.CategoryFilterOptions[i].Name < result.CategoryFilterOptions[j].Name
})
- for ind := range result.Problems {
- if result.Problems[ind].Category != nil {
- cid := result.Problems[ind].Category.ID
- for {
- if _, ok := par[cid]; ok {
- cid = par[cid]
- } else {
- break
- }
- }
-
- result.Problems[ind].CategoryLink = ui.Link{
- Text: categoryNameByID[cid],
- Href: fmt.Sprintf("/task_archive#category%d", result.Problems[ind].Category.ID),
- }
- }
- }
-
c.Set("title", tr.Translate("Problems"))
- return c.Render(http.StatusOK, "problemset/list", result)
+ return templates.Render(c, http.StatusOK, templates.ProblemList(result))
}
}
-type StatusPage struct {
- Pages []pagination.Link
- Submissions []njudge.Submission
+type GetStatusRequest struct {
+ AC string `query:"ac"`
+ UserID int `query:"user_id"`
+ Problemset string `query:"problem_set"`
+ Problem string `query:"problem"`
+ Page int `query:"page"`
}
-func GetStatus(slist njudge.SubmissionListQuery) echo.HandlerFunc {
- type request struct {
- AC string `query:"ac"`
- UserID int `query:"user_id"`
- Problemset string `query:"problem_set"`
- Problem string `query:"problem"`
- Page int `query:"page"`
- }
+func GetStatus(subList njudge.SubmissionListQuery) echo.HandlerFunc {
return func(c echo.Context) error {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
- data := request{}
+ data := GetStatusRequest{}
if err := c.Bind(&data); err != nil {
return err
}
@@ -273,24 +273,24 @@ func GetStatus(slist njudge.SubmissionListQuery) echo.HandlerFunc {
statusReq.Verdict = &ac
}
- submissionList, err := slist.GetPagedSubmissionList(c.Request().Context(), statusReq)
+ submissionList, err := subList.GetPagedSubmissionList(c.Request().Context(), statusReq)
if err != nil {
return err
}
qu := (*c.Request().URL).Query()
- links, err := pagination.LinksWithCountLimit(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu, 5)
+ links, err := templates.LinksWithCountLimit(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu, 5)
if err != nil {
return err
}
- result := StatusPage{
+ result := templates.SubmissionsViewModel{
Submissions: submissionList.Submissions,
Pages: links,
}
c.Set("title", tr.Translate("Submissions"))
- return c.Render(http.StatusOK, "status.gohtml", result)
+ return templates.Render(c, http.StatusOK, templates.Status(result))
}
}
diff --git a/internal/web/handlers/submission.go b/internal/web/handlers/submission.go
index 62647be3..7c006f46 100644
--- a/internal/web/handlers/submission.go
+++ b/internal/web/handlers/submission.go
@@ -1,24 +1,25 @@
package handlers
import (
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/i18n"
"github.com/mraron/njudge/internal/web/helpers/roles"
)
-func GetSubmission(s njudge.Submissions) echo.HandlerFunc {
- type request struct {
- ID int `param:"id"`
- }
+type GetSubmissionRequest struct {
+ ID int `param:"id"`
+}
+func GetSubmission(s njudge.Submissions) echo.HandlerFunc {
return func(c echo.Context) error {
+ u := c.Get("user").(*njudge.User)
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
- data := &request{}
+ data := &GetSubmissionRequest{}
if err := c.Bind(data); err != nil {
return err
}
@@ -28,8 +29,18 @@ func GetSubmission(s njudge.Submissions) echo.HandlerFunc {
return err
}
- c.Set("title", tr.Translate("Submission #%d", data.ID))
- return c.Render(http.StatusOK, "submission.gohtml", sub)
+ vm := templates.SubmissionViewModel{
+ Submission: *sub,
+ }
+ if u != nil && roles.Can(roles.Role(u.Role), roles.ActionCreate, "submissions/rejudge") {
+ vm.CanRejudge = true
+ }
+ if sub.Language != "zip" {
+ vm.DisplaySource = true
+ }
+
+ c.Set(templates.TitleContextKey, tr.Translate("Submission #%d", data.ID))
+ return templates.Render(c, http.StatusOK, templates.Submission(vm))
}
}
@@ -41,7 +52,7 @@ func RejudgeSubmission(s njudge.Submissions) echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
if !roles.Can(roles.Role(u.Role), roles.ActionCreate, "submissions/rejudge") {
- return helpers.UnauthorizedError(c)
+ return c.NoContent(http.StatusUnauthorized)
}
data := &request{}
diff --git a/internal/web/handlers/user/forgottenpassword.go b/internal/web/handlers/user/forgottenpassword.go
index a0b396fb..6c68b7a7 100644
--- a/internal/web/handlers/user/forgottenpassword.go
+++ b/internal/web/handlers/user/forgottenpassword.go
@@ -3,13 +3,13 @@ package user
import (
"bytes"
"errors"
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"time"
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
"github.com/mraron/njudge/internal/njudge/email"
- "github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/config"
"github.com/mraron/njudge/internal/web/helpers/i18n"
)
@@ -20,10 +20,10 @@ func GetForgottenPassword() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
- helpers.DeleteFlash(c, "ForgottenPasswordMessage")
+ templates.DeleteFlash(c, "ForgottenPasswordMessage")
return c.Render(http.StatusOK, "user/forgotten_password", nil)
}
@@ -37,7 +37,7 @@ func PostForgottenPassword(cfg config.Server, users njudge.Users, mailService em
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
data := request{}
@@ -81,7 +81,7 @@ func PostForgottenPassword(cfg config.Server, users njudge.Users, mailService em
}
- helpers.SetFlash(c, "ForgottenPasswordMessage", tr.Translate("An email with further instructions was sent to the given address (if it's registered in our system)."))
+ templates.SetFlash(c, "ForgottenPasswordMessage", tr.Translate("An email with further instructions was sent to the given address (if it's registered in our system)."))
return c.Redirect(http.StatusFound, c.Echo().Reverse("GetForgottenPassword"))
}
@@ -97,7 +97,7 @@ func GetForgottenPasswordForm() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
data := request{}
@@ -105,7 +105,7 @@ func GetForgottenPasswordForm() echo.HandlerFunc {
return err
}
- helpers.DeleteFlash(c, "ForgottenPasswordFormMessage")
+ templates.DeleteFlash(c, "ForgottenPasswordFormMessage")
return c.Render(http.StatusOK, "user/forgotten_password_form", struct {
Name string
@@ -126,7 +126,7 @@ func PostForgottenPasswordForm(users njudge.Users) echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
data := request{}
@@ -140,16 +140,16 @@ func PostForgottenPasswordForm(users njudge.Users) echo.HandlerFunc {
}
if u.ForgottenPasswordKey == nil || u.ForgottenPasswordKey.Key != data.Key || !u.ForgottenPasswordKey.IsValid() {
- helpers.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("Invalid key provided."))
+ templates.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("Invalid key provided."))
} else {
if data.Password1 != data.Password2 {
- helpers.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("The two passwords don't match."))
+ templates.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("The two passwords don't match."))
} else {
u.ForgottenPasswordKey = nil
u.SetPassword(data.Password1)
if err := users.Update(c.Request().Context(), u, njudge.Fields(njudge.UserFields.ForgottenPasswordKey, njudge.UserFields.Password)); err == nil {
- helpers.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("Password changed succesfully! You can login with your new password."))
+ templates.SetFlash(c, "ForgottenPasswordFormMessage", tr.Translate("Password changed succesfully! You can login with your new password."))
} else {
return err
}
diff --git a/internal/web/handlers/user/login.go b/internal/web/handlers/user/login.go
index ec182a9d..34899839 100644
--- a/internal/web/handlers/user/login.go
+++ b/internal/web/handlers/user/login.go
@@ -2,14 +2,13 @@ package user
import (
"errors"
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"github.com/markbates/goth/gothic"
"github.com/mraron/njudge/internal/njudge"
"github.com/mraron/njudge/internal/web/helpers/i18n"
- "github.com/mraron/njudge/internal/web/helpers"
-
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"golang.org/x/crypto/bcrypt"
@@ -38,22 +37,22 @@ func loginUserHandler(auth Authenticator) echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
user, err := auth(c)
if err != nil {
if errors.Is(err, ErrorLogin) {
- helpers.SetFlash(c, "LoginMessage", err.(LoginErrorWithMessage).TranslatedMessage)
+ templates.SetFlash(c, "LoginMessage", err.(LoginErrorWithMessage).TranslatedMessage)
return c.Redirect(http.StatusFound, c.Echo().Reverse("getUserLogin"))
} else {
return err
}
}
- defer helpers.DeleteFlash(c, "LoginRedirect")
+ defer templates.DeleteFlash(c, "LoginRedirect")
if !user.ActivationInfo.Activated {
- helpers.SetFlash(c, "LoginMessage", tr.Translate("The account is not activated. Check your emails!"))
+ templates.SetFlash(c, "LoginMessage", tr.Translate("The account is not activated. Check your emails!"))
return c.Redirect(http.StatusFound, "/user/login")
}
@@ -64,14 +63,14 @@ func loginUserHandler(auth Authenticator) echo.HandlerFunc {
return err
}
- c.Set("user", user)
+ c.Set(templates.UserContextKey, user)
to := "/"
- if val, ok := helpers.GetFlash(c, "LoginRedirect").(string); ok {
+ if val, ok := templates.GetFlash(c, "LoginRedirect").(string); ok {
to = val
}
- helpers.SetFlash(c, "TopMessage", tr.Translate("Successful login!"))
+ templates.SetFlash(c, templates.TopMessageContextKey, tr.Translate("Successful login!"))
return c.Redirect(http.StatusFound, to)
}
}
@@ -81,7 +80,7 @@ func BeginOAuth() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
gothic.BeginAuthHandler(c.Response(), c.Request())
@@ -94,16 +93,16 @@ func GetLogin() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
- helpers.DeleteFlash(c, "LoginMessage")
+ templates.DeleteFlash(c, "LoginMessage")
to := "/"
if val := c.QueryParams().Get("next"); val != "" {
to = val
}
- helpers.SetFlash(c, "LoginRedirect", to)
+ templates.SetFlash(c, "LoginRedirect", to)
return c.Render(http.StatusOK, "user/login", nil)
}
diff --git a/internal/web/handlers/user/middleware.go b/internal/web/handlers/user/middleware.go
index b7a12366..fa62853b 100644
--- a/internal/web/handlers/user/middleware.go
+++ b/internal/web/handlers/user/middleware.go
@@ -5,6 +5,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
"github.com/mraron/njudge/internal/web/helpers"
+ "github.com/mraron/njudge/internal/web/templates"
)
func currentUser(c echo.Context, us njudge.Users) (*njudge.User, error) {
@@ -31,7 +32,7 @@ func SetUserMiddleware(us njudge.Users) func(echo.HandlerFunc) echo.HandlerFunc
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
user, err := currentUser(c, us)
- c.Set("user", user)
+ c.Set(templates.UserContextKey, user)
if user != nil {
c.Set("userID", user.ID)
diff --git a/internal/web/handlers/user/profile/profile.go b/internal/web/handlers/user/profile/profile.go
index 261904dd..93b4e605 100644
--- a/internal/web/handlers/user/profile/profile.go
+++ b/internal/web/handlers/user/profile/profile.go
@@ -1,30 +1,28 @@
package profile
import (
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"golang.org/x/crypto/bcrypt"
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/handlers/problemset"
- "github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/i18n"
- "github.com/mraron/njudge/internal/web/helpers/pagination"
)
-func GetProfile(slist njudge.SubmissionListQuery) echo.HandlerFunc {
+func GetProfile(sublist njudge.SubmissionListQuery) echo.HandlerFunc {
return func(c echo.Context) error {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
u := c.Get("profile").(*njudge.User)
- solved, err := slist.GetSolvedSubmissionList(c.Request().Context(), u.ID)
+ solved, err := sublist.GetSolvedSubmissionList(c.Request().Context(), u.ID)
if err != nil {
return err
}
- attempted, err := slist.GetAttemptedSubmissionList(c.Request().Context(), u.ID)
+ attempted, err := sublist.GetAttemptedSubmissionList(c.Request().Context(), u.ID)
if err != nil {
return err
}
@@ -38,7 +36,7 @@ func GetProfile(slist njudge.SubmissionListQuery) echo.HandlerFunc {
}
}
-func GetSubmissions(slist njudge.SubmissionListQuery) echo.HandlerFunc {
+func GetSubmissions(sublist njudge.SubmissionListQuery) echo.HandlerFunc {
type request struct {
Page int `query:"page"`
}
@@ -64,18 +62,18 @@ func GetSubmissions(slist njudge.SubmissionListQuery) echo.HandlerFunc {
UserID: u.ID,
}
- submissionList, err := slist.GetPagedSubmissionList(c.Request().Context(), statusReq)
+ submissionList, err := sublist.GetPagedSubmissionList(c.Request().Context(), statusReq)
if err != nil {
return err
}
qu := (*c.Request().URL).Query()
- links, err := pagination.Links(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu)
+ links, err := templates.Links(submissionList.PaginationData.Page, submissionList.PaginationData.PerPage, int64(submissionList.PaginationData.Count), qu)
if err != nil {
return err
}
- result := problemset.StatusPage{
+ result := templates.SubmissionsViewModel{
Submissions: submissionList.Submissions,
Pages: links,
}
@@ -83,7 +81,7 @@ func GetSubmissions(slist njudge.SubmissionListQuery) echo.HandlerFunc {
c.Set("title", tr.Translate("%s's submissions", u.Name))
return c.Render(http.StatusOK, "user/profile/submissions", struct {
User *njudge.User
- StatusPage problemset.StatusPage
+ StatusPage templates.SubmissionsViewModel
}{u, result})
}
}
@@ -92,7 +90,7 @@ func GetSettings() echo.HandlerFunc {
return func(c echo.Context) error {
u := c.Get("user").(*njudge.User)
- helpers.DeleteFlash(c, "ChangePassword")
+ templates.DeleteFlash(c, "ChangePassword")
return c.Render(http.StatusOK, "user/profile/settings", struct {
User *njudge.User
}{u})
@@ -115,17 +113,17 @@ func PostSettingsChangePassword(us njudge.Users) echo.HandlerFunc {
}
if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(data.PasswordOld)); err != nil {
- helpers.SetFlash(c, "ChangePassword", tr.Translate("Wrong old password."))
+ templates.SetFlash(c, "ChangePassword", tr.Translate("Wrong old password."))
return c.Redirect(http.StatusFound, "../")
}
if len(data.PasswordNew1) == 0 {
- helpers.SetFlash(c, "ChangePassword", tr.Translate("It's required to give a new password."))
+ templates.SetFlash(c, "ChangePassword", tr.Translate("It's required to give a new password."))
return c.Redirect(http.StatusFound, "../")
}
if data.PasswordNew1 != data.PasswordNew2 {
- helpers.SetFlash(c, "ChangePassword", tr.Translate("The two given passwords doesn't match."))
+ templates.SetFlash(c, "ChangePassword", tr.Translate("The two given passwords doesn't match."))
return c.Redirect(http.StatusFound, "../")
}
diff --git a/internal/web/handlers/user/register.go b/internal/web/handlers/user/register.go
index 6d82896d..4b6f2fbc 100644
--- a/internal/web/handlers/user/register.go
+++ b/internal/web/handlers/user/register.go
@@ -3,6 +3,7 @@ package user
import (
"bytes"
"errors"
+ "github.com/mraron/njudge/internal/web/templates"
"net/http"
"unicode"
@@ -149,7 +150,7 @@ func GetActivateInfo() echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
return c.Render(http.StatusOK, "user/activate.gohtml", nil)
@@ -170,7 +171,7 @@ func Activate(users njudge.Users) echo.HandlerFunc {
tr := c.Get(i18n.TranslatorContextKey).(i18n.Translator)
if u := c.Get("user").(*njudge.User); u != nil {
- return c.Render(http.StatusOK, "error.gohtml", tr.Translate(alreadyLoggedInMessage))
+ return templates.Render(c, http.StatusOK, templates.Error(tr.Translate(alreadyLoggedInMessage)))
}
user, err := users.GetByName(c.Request().Context(), data.Name)
diff --git a/internal/web/helpers/config/config.go b/internal/web/helpers/config/config.go
index 20105ee1..e670437f 100644
--- a/internal/web/helpers/config/config.go
+++ b/internal/web/helpers/config/config.go
@@ -1,13 +1,8 @@
package config
import (
- "crypto/rsa"
- "crypto/x509"
"database/sql"
- "encoding/pem"
- "errors"
"fmt"
- "io/ioutil"
"log/slog"
"time"
)
@@ -86,59 +81,4 @@ type Server struct {
} `json:"smtp" mapstructure:"smtp"`
Database `json:"database" mapstructure:"database"`
-
- Keys Keys
-}
-
-type Keys struct {
- PrivateKeyLocation string `json:"private_key" mapstructure:"private_key"`
- PublicKeyLocation string `json:"public_key" mapstructure:"public_key"`
- PrivateKey *rsa.PrivateKey
- PublicKey *rsa.PublicKey
-}
-
-func (k *Keys) Parse() error {
- if k.PrivateKeyLocation != "" {
- if k.PublicKeyLocation == "" {
- return errors.New("private key filled, public not")
- }
-
- privateKeyContents, err := ioutil.ReadFile(k.PrivateKeyLocation)
- if err != nil {
- return err
- }
-
- block, _ := pem.Decode(privateKeyContents)
- if block == nil {
- return fmt.Errorf("can't parse pem private key file: %s", k.PrivateKeyLocation)
- }
-
- var pKey any
- if pKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
- return err
- }
- k.PrivateKey = pKey.(*rsa.PrivateKey)
-
- publicKeyContents, err := ioutil.ReadFile(k.PublicKeyLocation)
- if err != nil {
- return err
- }
-
- block, _ = pem.Decode(publicKeyContents)
- if block == nil {
- return fmt.Errorf("can't parse pem public key file: %s", k.PrivateKeyLocation)
- }
-
- if k.PublicKey, err = x509.ParsePKCS1PublicKey(block.Bytes); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func (k *Keys) MustParse() {
- if err := k.Parse(); err != nil {
- panic(err)
- }
}
diff --git a/internal/web/helpers/helpers.go b/internal/web/helpers/helpers.go
index 23bd9bbb..f14f1d34 100644
--- a/internal/web/helpers/helpers.go
+++ b/internal/web/helpers/helpers.go
@@ -1,15 +1,10 @@
package helpers
import (
- "errors"
- "net/http"
- "time"
-
- "github.com/mraron/njudge/internal/njudge/db/models"
- "github.com/mraron/njudge/internal/web/helpers/config"
-
- "github.com/golang-jwt/jwt"
"github.com/labstack/echo/v4"
+ "github.com/mraron/njudge/internal/njudge/db/models"
+ "github.com/mraron/njudge/internal/web/templates"
+ "net/http"
)
func CensorUserPassword(user *models.User) {
@@ -17,35 +12,10 @@ func CensorUserPassword(user *models.User) {
}
func LoginRequired(c echo.Context) error {
- SetFlash(c, "LoginMessage", "A kért oldal megtekintéséhez belépés szükséges!")
+ templates.SetFlash(c, "LoginMessage", "A kért oldal megtekintéséhez belépés szükséges!")
to := ""
if c.Request().Method == "GET" {
to = "?next=" + c.Request().URL.Path
}
return c.Redirect(http.StatusFound, "/user/login"+to)
}
-
-func UnauthorizedError(c echo.Context) error {
- return echo.NewHTTPError(http.StatusUnauthorized, errors.New("unauthorized"))
-}
-
-func GetJWT(cfg config.Keys) (string, error) {
- if cfg.PrivateKey == nil {
- return "", nil
- }
-
- claims := &jwt.StandardClaims{
- ExpiresAt: time.Now().Add(10 * time.Minute).Unix(),
- NotBefore: time.Now().Unix(),
- Issuer: "njudge web",
- IssuedAt: time.Now().Unix(),
- }
-
- token := jwt.NewWithClaims(jwt.SigningMethodRS512, claims)
- jwt, err := token.SignedString(cfg.PrivateKey)
- if err != nil {
- return "", err
- }
-
- return jwt, nil
-}
diff --git a/internal/web/helpers/templates/funcs.go b/internal/web/helpers/templates/funcs.go
index 2e9fc4a5..61843a23 100644
--- a/internal/web/helpers/templates/funcs.go
+++ b/internal/web/helpers/templates/funcs.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "github.com/mraron/njudge/internal/web/templates"
"github.com/mraron/njudge/pkg/language/memory"
"html/template"
"math"
@@ -16,10 +17,8 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/mraron/njudge/internal/njudge"
- "github.com/mraron/njudge/internal/web/helpers"
"github.com/mraron/njudge/internal/web/helpers/i18n"
"github.com/mraron/njudge/internal/web/helpers/roles"
- "github.com/mraron/njudge/internal/web/helpers/templates/partials"
"github.com/mraron/njudge/pkg/problems"
"golang.org/x/text/message"
)
@@ -52,7 +51,7 @@ func contextFuncs(c echo.Context) template.FuncMap {
return &val.Value
},
"getFlash": func(name string) interface{} {
- return helpers.GetFlash(c, name)
+ return templates.GetFlash(c, name)
},
"csrf": func() string {
return c.Get(middleware.DefaultCSRFConfig.ContextKey).(string)
@@ -66,7 +65,7 @@ func contextFuncs(c echo.Context) template.FuncMap {
}
}
-func statelessFuncs(store problems.Store, users njudge.Users, ps njudge.Problems, tags njudge.Tags, store2 partials.Store) template.FuncMap {
+func statelessFuncs(store problems.Store, users njudge.Users, ps njudge.Problems, tags njudge.Tags, store2 templates.Store) template.FuncMap {
return template.FuncMap{
"translateContent": i18n.TranslateContent,
"problem": store.GetProblem,
diff --git a/internal/web/helpers/templates/templates.go b/internal/web/helpers/templates/templates.go
index 34d4d797..d125208d 100644
--- a/internal/web/helpers/templates/templates.go
+++ b/internal/web/helpers/templates/templates.go
@@ -17,7 +17,6 @@ import (
"github.com/labstack/echo/v4"
"github.com/mraron/njudge/internal/web/helpers/config"
- "github.com/mraron/njudge/internal/web/helpers/templates/partials"
"github.com/mraron/njudge/pkg/problems"
)
@@ -28,12 +27,12 @@ type Renderer struct {
users njudge.Users
problems njudge.Problems
tags njudge.Tags
- partialsStore partials.Store
+ partialsStore templates.Store
sync.RWMutex
}
-func New(cfg config.Server, problemStore problems.Store, users njudge.Users, ps njudge.Problems, tags njudge.Tags, partialsStore partials.Store) *Renderer {
+func New(cfg config.Server, problemStore problems.Store, users njudge.Users, ps njudge.Problems, tags njudge.Tags, partialsStore templates.Store) *Renderer {
renderer := &Renderer{
templates: make(map[string]*template.Template),
cfg: cfg,
diff --git a/internal/web/helpers/ui/link.go b/internal/web/helpers/ui/link.go
deleted file mode 100644
index 1360d269..00000000
--- a/internal/web/helpers/ui/link.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package ui
-
-type Link struct {
- Text string
- Href string
-}
diff --git a/internal/web/helpers/ui/sortcolumn.go b/internal/web/helpers/ui/sortcolumn.go
deleted file mode 100644
index 8285fcbf..00000000
--- a/internal/web/helpers/ui/sortcolumn.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package ui
-
-type SortColumn struct {
- Order string
- Href string
-}
diff --git a/internal/web/routes.go b/internal/web/routes.go
index f90af303..b5d6b982 100644
--- a/internal/web/routes.go
+++ b/internal/web/routes.go
@@ -1,6 +1,7 @@
package web
import (
+ "github.com/mraron/njudge/internal/web/templates"
"strings"
"github.com/labstack/echo/v4/middleware"
@@ -14,7 +15,6 @@ import (
"github.com/mraron/njudge/internal/web/handlers/taskarchive"
"github.com/mraron/njudge/internal/web/handlers/user"
"github.com/mraron/njudge/internal/web/handlers/user/profile"
- "github.com/mraron/njudge/internal/web/helpers"
)
func (s *Server) prepareRoutes(e *echo.Echo) {
@@ -27,9 +27,11 @@ func (s *Server) prepareRoutes(e *echo.Echo) {
}))
e.Use(i18n.SetTranslatorMiddleware())
e.Use(user.SetUserMiddleware(s.Users))
- e.Use(helpers.ClearTemporaryFlashes())
+ e.Use(templates.MoveFlashesToContextMiddleware())
+ e.Use(templates.ClearTemporaryFlashesMiddleware())
+ e.Use(templates.Middleware(s.Users, s.Problems, s.ProblemStore, s.PartialsStore))
- e.GET("/", handlers.GetHome())
+ e.GET("/", handlers.GetHome(s.PartialsStore))
e.GET("/page/:page", handlers.GetPage(s.PartialsStore))
e.Static("/static", "static")
@@ -39,7 +41,7 @@ func (s *Server) prepareRoutes(e *echo.Echo) {
e.GET("/task_archive", taskarchive.Get(s.Categories, s.ProblemQuery, s.SolvedStatusQuery, s.ProblemStore))
ps := e.Group("/problemset", problemset.SetNameMiddleware())
- ps.GET("/:name/", problemset.GetProblemList(s.ProblemStore, s.Problems, s.Categories, s.ProblemListQuery, s.ProblemInfoQuery))
+ ps.GET("/:name/", problemset.GetProblemList(s.ProblemStore, s.Problems, s.Categories, s.ProblemListQuery, s.ProblemInfoQuery, s.Tags))
ps.POST("/:name/submit", problemset.PostSubmit(s.SubmitService), user.RequireLoginMiddleware())
ps.GET("/status/", problemset.GetStatus(s.SubmissionListQuery)).Name = "getProblemsetStatus"
@@ -123,6 +125,6 @@ func (s *Server) prepareRoutes(e *echo.Echo) {
v1.PUT("/submissions/:id", api.Put[models.Submission](submissionDataProvider))
v1.DELETE("/submissions/:id", api.Delete[models.Submission](submissionDataProvider))
- e.GET("/admin", handlers.GetAdmin(s.Server), user.RequireLoginMiddleware())
+ e.GET("/admin", handlers.GetAdmin(), user.RequireLoginMiddleware())
}
}
diff --git a/internal/web/server.go b/internal/web/server.go
index 79180963..d0aa41d5 100644
--- a/internal/web/server.go
+++ b/internal/web/server.go
@@ -1,18 +1,16 @@
package web
import (
- "context"
"database/sql"
+ "github.com/mraron/njudge/internal/web/templates"
_ "mime"
"github.com/mraron/njudge/internal/njudge"
"github.com/mraron/njudge/internal/njudge/email"
- "github.com/mraron/njudge/internal/web/helpers/config"
- "github.com/mraron/njudge/internal/web/helpers/templates/partials"
-
"github.com/labstack/echo/v4"
_ "github.com/lib/pq"
+ "github.com/mraron/njudge/internal/web/helpers/config"
"github.com/mraron/njudge/pkg/problems"
_ "github.com/mraron/njudge/pkg/problems/config/feladat_txt"
_ "github.com/mraron/njudge/pkg/problems/config/polygon"
@@ -30,7 +28,7 @@ type Server struct {
ProblemStore problems.Store
MailService email.Service
- PartialsStore partials.Store
+ PartialsStore templates.Store
Categories njudge.Categories
Tags njudge.Tags
@@ -60,18 +58,3 @@ func (s *Server) Run() {
panic(s.e.Start(":" + s.Port))
}
-
-func (s *Server) Submit(uid int, problemset, problem, language string, source []byte) (int, error) {
- sub, err := s.SubmitService.Submit(context.Background(), njudge.SubmitRequest{
- UserID: uid,
- Problemset: problemset,
- Problem: problem,
- Language: language,
- Source: source,
- })
-
- if err != nil {
- return -1, err
- }
- return sub.ID, nil
-}
diff --git a/internal/web/templates/404.gohtml b/internal/web/templates/404.gohtml
deleted file mode 100644
index e9404c62..00000000
--- a/internal/web/templates/404.gohtml
+++ /dev/null
@@ -1,6 +0,0 @@
-{{template "header" .}}
-
-Upsz!
-{{.Data}}
-
-{{template "footer" .}}
\ No newline at end of file
diff --git a/internal/web/templates/_layout.gohtml b/internal/web/templates/_layout.gohtml
index 8d4277b1..c68e4aec 100644
--- a/internal/web/templates/_layout.gohtml
+++ b/internal/web/templates/_layout.gohtml
@@ -22,6 +22,8 @@
+
+
{{ str2html (partial "custom_head") }}