diff --git a/.gitignore b/.gitignore index e07f97f..f9e5dd9 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,5 @@ __debug_bin* cmd/goSign/lc_* EXPERIMENT_* -web/public/fixtures \ No newline at end of file +web/public/fixtures +gosign.toml \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index e977338..278df48 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,6 +9,7 @@ "program": "${workspaceFolder}/cmd/goSign", "envFile": "${workspaceFolder}/docker/.env", "args": ["serve"], + //"args": ["gen", "--config"], }, { "name": "pdf", diff --git a/cmd/cert/main.go b/cmd/cert/main.go index df9211b..5a4bc6a 100644 --- a/cmd/cert/main.go +++ b/cmd/cert/main.go @@ -17,43 +17,43 @@ var ( func main() { // CA cert - pkey, err := generatePrivateKey(caKeyPath) + pKey, err := generatePrivateKey(caKeyPath) if err != nil { log.Fatal(err) } fmt.Println("CA private key file generated", caKeyPath) - caCert, err := generateCA(pkey.PrivateKey) + caCert, err := generateCA(pKey.PrivateKey) if err != nil { log.Fatal(err) } fmt.Println("CA certificate file generated") - if err := generateCRL(pkey.PrivateKey, caCert.Cert); err != nil { + if err := generateCRL(pKey.PrivateKey, caCert.Cert); err != nil { log.Fatal(err) } fmt.Println("CRL file generated", caCRLPath) // CA Intermed cert - ipkey, err := generatePrivateKey(caInterKeyPath) + ipKey, err := generatePrivateKey(caInterKeyPath) if err != nil { log.Fatal(err) } fmt.Println("Private key file generated", caInterKeyPath) - if err := generateIntermediateCert(ipkey.PrivateKey); err != nil { + if err := generateIntermediateCert(ipKey.PrivateKey); err != nil { log.Fatal(err) } fmt.Println("CA Intermed certificate file generated") // user cert - upkey, err := generatePrivateKey(uKeyPath) + upKey, err := generatePrivateKey(uKeyPath) if err != nil { log.Fatal(err) } fmt.Println("user private key file generated", uKeyPath) - if err := generateCert(upkey.PrivateKey); err != nil { + if err := generateCert(upKey.PrivateKey); err != nil { log.Fatal(err) } fmt.Println("user certificate file generated", uPath) diff --git a/cmd/goSign/main.go b/cmd/goSign/main.go index d625f6a..7dd3e99 100644 --- a/cmd/goSign/main.go +++ b/cmd/goSign/main.go @@ -31,6 +31,7 @@ func main() { }) rootCmd.AddCommand(cmdServe()) + rootCmd.AddCommand(cmdGen()) if err := rootCmd.Execute(); err != nil { os.Exit(1) @@ -50,3 +51,25 @@ func cmdServe() *cobra.Command { return cmd } + +func cmdGen() *cobra.Command { + var configFile, keyJWT, keyLicense bool + cmd := &cobra.Command{ + Use: "gen [flags]", + Short: "Generate keys and config files", + Run: func(serveCmd *cobra.Command, args []string) { + if !configFile && !keyJWT && !keyLicense { + serveCmd.Help() + } + if configFile { + if err := app.GenConfigFile(); err != nil { + fmt.Print("Config file generated") + os.Exit(1) + } + } + }, + } + + cmd.PersistentFlags().BoolVar(&configFile, "config", false, "config file") + return cmd +} diff --git a/go.mod b/go.mod index 0223ccb..f6a10fb 100644 --- a/go.mod +++ b/go.mod @@ -7,17 +7,19 @@ require ( github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 - github.com/gofiber/contrib/fiberzerolog v1.0.0 + github.com/gofiber/contrib/fiberzerolog v1.0.1 github.com/gofiber/fiber/v2 v2.52.4 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.5.5 - github.com/joho/godotenv v1.5.1 github.com/mattetti/filebuffer v1.0.1 - github.com/pressly/goose/v3 v3.19.2 + github.com/pdfcpu/pdfcpu v0.8.0 + github.com/pelletier/go-toml/v2 v2.2.1 + github.com/pressly/goose/v3 v3.20.0 github.com/redis/go-redis/v9 v9.5.1 + github.com/robfig/cron/v3 v3.0.0 github.com/rs/zerolog v1.32.0 - github.com/signintech/gopdf v0.24.0 + github.com/signintech/gopdf v0.25.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/spf13/cobra v1.8.0 golang.org/x/crypto v0.22.0 @@ -29,11 +31,14 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/hhrutter/lzw v1.0.0 // indirect + github.com/hhrutter/tiff v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/klauspost/compress v1.17.8 // indirect + github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect @@ -42,6 +47,7 @@ require ( github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tinylib/msgp v1.1.9 // indirect @@ -49,6 +55,11 @@ require ( github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect + golang.org/x/image v0.15.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect + modernc.org/libc v1.50.2 // indirect + modernc.org/sqlite v1.29.8 // indirect ) diff --git a/go.sum b/go.sum index 16d2e34..238623d 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,5 @@ -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= -github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= -github.com/ClickHouse/clickhouse-go/v2 v2.17.1 h1:ZCmAYWpu75IyEi7+Yrs/uaAjiCGY5wfW5kXo64exkX4= -github.com/ClickHouse/clickhouse-go/v2 v2.17.1/go.mod h1:rkGTvFDTLqLIm0ma+13xmcCfr/08Gvs7KmFt1tgiWHQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -21,14 +7,11 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= -github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -41,49 +24,25 @@ github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQM github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 h1:lxmTCgmHE1GUYL7P0MlNa00M67axePTq+9nBSGddR8I= github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7/go.mod h1:GvWntX9qiTlOud0WkQ6ewFm0LPy5JUR1Xo0Ngbd1w6Y= -github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= -github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elastic/go-sysinfo v1.11.2 h1:mcm4OSYVMyws6+n2HIVMGkln5HOpo5Ie1ZmbbNn0jg4= -github.com/elastic/go-sysinfo v1.11.2/go.mod h1:GKqR8bbMK/1ITnez9NIsIfXQr25aLhRJa7AfT8HpBFQ= -github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= -github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= -github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= -github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= -github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= -github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= -github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4= -github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofiber/contrib/fiberzerolog v1.0.0 h1:IB8q+NO2zPNS4VHKde1x5DqtMJ5vGrvDCydnAjlFw3E= -github.com/gofiber/contrib/fiberzerolog v1.0.0/go.mod h1:SOi+Wo7RQlO/HV0jsYTu6uFQy+8ZPTzCZW4fDEKD3l8= +github.com/gofiber/contrib/fiberzerolog v1.0.1 h1:kKIlD1v72Iy9/PW3z5nyZ1XeAAO1ZNIl8oKGen0BiV4= +github.com/gofiber/contrib/fiberzerolog v1.0.1/go.mod h1:bDsXnPPGUVTETnl9KfzoTgLABYFxDdIjSabLqU763Do= github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0= +github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo= +github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0= +github.com/hhrutter/tiff v1.0.1/go.mod h1:zU/dNgDm0cMIa8y8YwcYBeuEEveI4B0owqHyiPpJPHc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -94,16 +53,12 @@ github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= -github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 h1:6PfEMwfInASh9hkN83aR0j4W/eKaAZt/AURtXAXlas0= -github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475/go.mod h1:20nXSmcf0nAscrzqsXeC2/tA3KkV2eCiJqYuyAgl+ss= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM= github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -116,37 +71,23 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= -github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= -github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s= -github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/pdfcpu/pdfcpu v0.8.0 h1:SuEB4uVsPFz1nb802r38YpFpj9TtZh/oB0bGG34IRZw= +github.com/pdfcpu/pdfcpu v0.8.0/go.mod h1:jj03y/KKrwigt5xCi8t7px2mATcKuOzkIOoCX62yMho= +github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= +github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 h1:zyWXQ6vu27ETMpYsEMAsisQ+GqJ4e1TPvSNfdOPF0no= github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= -github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pressly/goose/v3 v3.19.2 h1:z1yuD41jS4iaqLkyjkzGkKBz4rgyz/BYtCyMMGHlgzQ= -github.com/pressly/goose/v3 v3.19.2/go.mod h1:BHkf3LzSBmO8E5FTMPupUYIpMTIh/ZuQVy+YTfhZLD4= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/pressly/goose/v3 v3.20.0 h1:uPJdOxF/Ipj7ABVNOAMJXSxwFXZGwMGHNqjC8e61VA0= +github.com/pressly/goose/v3 v3.20.0/go.mod h1:BRfF2GcG4FTG12QfdBVy3q1yveaf4ckL9vWwEcIO3lA= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -154,20 +95,18 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E= +github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= -github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/signintech/gopdf v0.24.0 h1:1V0LCbe9A8E2mDYtdLW5/vOiT9jPQHjebTnSrLUVwe0= -github.com/signintech/gopdf v0.24.0/go.mod h1:wrLtZoWaRNrS4hphED0oflFoa6IWkOu6M3nJjm4VbO4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/signintech/gopdf v0.25.0 h1:w+C1RWe89yHqrdU9WZwMoUvmUeeQhNxrmJWfN2h6plQ= +github.com/signintech/gopdf v0.25.0/go.mod h1:d23eO35GpEliSrF22eJ4bsM3wVeQJTjXTHq5x5qGKjA= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= @@ -175,47 +114,31 @@ github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyh github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.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/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= -github.com/tursodatabase/libsql-client-go v0.0.0-20240220085343-4ae0eb9d0898 h1:1MvEhzI5pvP27e9Dzz861mxk9WzXZLSJwzOU67cKTbU= -github.com/tursodatabase/libsql-client-go v0.0.0-20240220085343-4ae0eb9d0898/go.mod h1:9bKuHS7eZh/0mJndbUOrCx8Ej3PlsRDszj4L7oVYMPQ= 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/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= -github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/ydb-platform/ydb-go-genproto v0.0.0-20240126124512-dbb0e1720dbf h1:ckwNHVo4bv2tqNkgx3W3HANh3ta1j6TR5qw08J1A7Tw= -github.com/ydb-platform/ydb-go-genproto v0.0.0-20240126124512-dbb0e1720dbf/go.mod h1:Er+FePu1dNUieD+XTMDduGpQuCPssK5Q4BjF+IIXJ3I= -github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1 h1:Ebo6J5AMXgJ3A438ECYotA0aK7ETqjQx9WoZvVxzKBE= -github.com/ydb-platform/ydb-go-sdk/v3 v3.55.1/go.mod h1:udNPW8eupyH/EZocecFmaSNJacKKYjzQa7cVgX5U2nc= -go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc= -go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs= -go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ= -go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= -golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -225,36 +148,26 @@ 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/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= -howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= -modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8= +modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.50.2 h1:I0+3wlRvXmAEjAJvD7BhP1kmKHwkzV0rOcqFcD85u+0= +modernc.org/libc v1.50.2/go.mod h1:Fd8TZdfRorOd1vB0QCtYSHYAuzobS4xS3mhMGUkeVcA= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE= -modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/sqlite v1.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= +modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= diff --git a/internal/app.go b/internal/app.go index 6012fee..fa6387f 100644 --- a/internal/app.go +++ b/internal/app.go @@ -7,10 +7,12 @@ import ( "os/signal" "github.com/gofiber/fiber/v2" - "github.com/joho/godotenv" + "github.com/robfig/cron/v3" + "github.com/shurco/gosign/internal/config" + "github.com/shurco/gosign/internal/queries" "github.com/shurco/gosign/internal/routes" - "github.com/shurco/gosign/pkg/config" + "github.com/shurco/gosign/internal/trust" "github.com/shurco/gosign/pkg/logging" "github.com/shurco/gosign/pkg/storage/postgres" "github.com/shurco/gosign/pkg/storage/redis" @@ -18,45 +20,62 @@ import ( ) func New() error { - log := logging.Log + fmt.Print("✍️ Sign documents without stress\n") - godotenv.Load(".env", "./.env") + log := logging.Log - // directories init - if err := dirInit(); err != nil { + if err := config.Load(); err != nil { log.Err(err).Send() return err } + cfg := config.Data() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + // directories create + if err := createDirs(); err != nil { + log.Err(err).Send() + return err + } // redis init - redis.NewClient( - ctx, - config.GetString("REDIS_ADDR", "localhost:6379"), - config.GetString("REDIS_PASSWORD", "redisPassword"), - ) - defer redis.Conn.Close() + redis.New(context.Background(), cfg.Redis.Address, cfg.Redis.Password) if err := redis.Conn.Ping(); err != nil { log.Err(err).Send() return err } + defer redis.Conn.Close() + + // postgresql init + pool, err := postgres.New(context.Background(), cfg.Postgres) + if err != nil { + log.Err(err).Send() + return err + } + defer pool.Close() + + // db init + if err := queries.Init(pool); err != nil { + log.Err(err).Send() + return err + } + + // update trust certs + if err = trust.Update(cfg.Trust); err != nil { + log.Err(err).Send() + return err + } - // pastgresql init - err := postgres.NewClient(ctx, &postgres.PgSQLConfig{ - DSN: fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=require", - config.GetString("POSTGRES_USER", "goSign"), - config.GetString("POSTGRES_PASSWORD", "postgresPassword"), - config.GetString("POSTGRES_HOST", "localhost:5432"), - config.GetString("POSTGRES_DB", "goSign"), - ), + task := cron.New() + _, err = task.AddFunc("0 */12 * * *", func() { + fmt.Print("cron") + if err := trust.Update(cfg.Trust); err != nil { + log.Err(err).Send() + } }) if err != nil { log.Err(err).Send() return err } - defer postgres.Pool.Close() + task.Start() // web init app := fiber.New(fiber.Config{ @@ -73,24 +92,30 @@ func New() error { routes.ApiRoutes(app) routes.NotFoundRoute(app) - fmt.Print("✍️ Sign documents without stress\n") + fmt.Printf("├─[🚀] Admin UI: http://%s/_/\n", cfg.HTTPAddr) + fmt.Printf("├─[🚀] Public UI: http://%s/\n", cfg.HTTPAddr) + fmt.Printf("└─[🚀] Public API: http://%s/api/\n", cfg.HTTPAddr) - idleConnsClosed := make(chan struct{}) - go func() { - sigint := make(chan os.Signal, 1) - signal.Notify(sigint, os.Interrupt) - <-sigint + if cfg.DevMode { + StartServer(cfg.HTTPAddr, app) + } else { + idleConnsClosed := make(chan struct{}) - if err := app.Shutdown(); err != nil { - log.Err(err).Send() - } + go func() { + sigint := make(chan os.Signal, 1) + signal.Notify(sigint, os.Interrupt) + <-sigint + + if err := app.Shutdown(); err != nil { + log.Err(err).Send() + } - close(idleConnsClosed) - }() + close(idleConnsClosed) + }() - appPort := config.GetString("APP_PORT", ":8080") - StartServer(appPort, app) - <-idleConnsClosed + StartServer(cfg.HTTPAddr, app) + <-idleConnsClosed + } return nil } @@ -105,7 +130,7 @@ func StartServer(addr string, a *fiber.App) { } } -func dirInit() error { +func createDirs() error { dirsToCheck := []struct { path string name string diff --git a/internal/base/base.go b/internal/base/base.go deleted file mode 100644 index c1fc421..0000000 --- a/internal/base/base.go +++ /dev/null @@ -1,48 +0,0 @@ -package base - -import ( - "database/sql" - "embed" - "fmt" - - "github.com/pressly/goose/v3" - "github.com/shurco/gosign/pkg/utils/fsutil" -) - -// New is ... -func New(dbPath string, migrations embed.FS) (db *sql.DB, err error) { - if !fsutil.IsFile(dbPath) { - // create db - if _, err = fsutil.OpenFile(dbPath, fsutil.FsCWFlags, 0o666); err != nil { - return - } - - // first migrate db - if err = Migrate(dbPath, migrations); err != nil { - return - } - } - - // connect to database - dsn := fmt.Sprintf("%s?_pragma=busy_timeout(10000)&_pragma=journal_mode(WAL)&_pragma=journal_size_limit(200000000)&_pragma=synchronous(NORMAL)&_pragma=foreign_keys(ON)", dbPath) - db, err = sql.Open("sqlite", dsn) - db.Query("PRAGMA auto_vacuum") - - return -} - -// Migrate is ... -func Migrate(dbPath string, migrations embed.FS) (err error) { - goose.SetBaseFS(migrations) - var db *sql.DB - db, err = goose.OpenDBWithDriver("sqlite", dbPath) - if err != nil { - return - } - defer db.Close() - - goose.SetTableName("migrate_db_version") - - err = goose.Up(db, ".") - return -} diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..782f53e --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,86 @@ +package config + +import ( + "os" + + "github.com/pelletier/go-toml/v2" + + "github.com/shurco/gosign/internal/trust" + "github.com/shurco/gosign/pkg/storage/postgres" + "github.com/shurco/gosign/pkg/storage/redis" + "github.com/shurco/gosign/pkg/utils/fsutil" +) + +const ( + ConfigFile = "./gosign.toml" +) + +var cfg *Config + +// Config is ... +type Config struct { + HTTPAddr string `toml:"http-addr" comment:"Ports <= 1024 are privileged ports. You can't use them unless you're root or have the explicit\npermission to use them. See this answer for an explanation or wikipedia or something you trust more.\nsudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary"` + DevMode bool `toml:"dev-mode" comment:"Active develop mode"` + Postgres postgres.Config `toml:"postgres" comment:"Postgres section"` + Redis redis.Config `toml:"redis" comment:"Redis section"` + Trust trust.Config `toml:"trust-certs" comment:"Trust certs section"` +} + +// DefaultConfig is ... +func Default() *Config { + return &Config{ + DevMode: false, + HTTPAddr: "0.0.0.0:8088", + Postgres: postgres.Config{ + URL: "postgres://goSign:postgresPassword@localhost:5432/goSign?pool_max_conns=10", + }, + Redis: redis.Config{ + Address: "localhost:6379", + Password: "redisPassword", + }, + Trust: trust.Config{ + List: []string{"eutl12", "tl12"}, + Update: 1, + }, + } +} + +// Load is ... +func Load() error { + config := Default() + + if fsutil.IsFile(ConfigFile) { + file, err := os.ReadFile(ConfigFile) + if err != nil { + return err + } + + if err := toml.Unmarshal(file, &config); err != nil { + return err + } + } + + cfg = config + return nil +} + +// Save is ... +func Save(config *Config) error { + byteConfig, err := toml.Marshal(config) + if err != nil { + return err + } + if err := os.WriteFile(ConfigFile, byteConfig, 0o666); err != nil { + return err + } + + return nil +} + +// Data is ... +func Data() *Config { + if cfg == nil { + cfg = Default() + } + return cfg +} diff --git a/internal/gen.go b/internal/gen.go new file mode 100644 index 0000000..365404d --- /dev/null +++ b/internal/gen.go @@ -0,0 +1,12 @@ +package app + +import "github.com/shurco/gosign/internal/config" + +// GenConfigFile is ... +func GenConfigFile() error { + cfg := config.Default() + if err := config.Save(cfg); err != nil { + return err + } + return nil +} diff --git a/internal/handlers/private/edit.go b/internal/handlers/private/edit.go index 9e14ef7..cab72b5 100644 --- a/internal/handlers/private/edit.go +++ b/internal/handlers/private/edit.go @@ -5,103 +5,19 @@ import ( "github.com/gofiber/fiber/v2" - "github.com/shurco/gosign/internal/models" + "github.com/shurco/gosign/internal/queries" "github.com/shurco/gosign/pkg/logging" - "github.com/shurco/gosign/pkg/storage/postgres" "github.com/shurco/gosign/pkg/utils/webutil" ) func Template(c *fiber.Ctx) error { template := "00c95859-98ef-42cd-a801-2023b75a9431" - response := &models.Template{} - // template info - err := postgres.Pool.QueryRow(context.Background(), ` - SELECT - template.id, - template.slug, - template.name, - template.folder_id, - template.submitters, - template.fields, - template.schema, - template.created_at, - template.updated_at - FROM - "template" - WHERE - "template"."id" = $1 - `, template).Scan( - &response.ID, - &response.Slug, - &response.Name, - &response.FolderID, - &response.Submitters, - &response.Fields, - &response.Schema, - &response.CreatedAt, - &response.UpdatedAt, - ) + response, err := queries.DB.Template(context.Background(), template) if err != nil { logging.Log.Err(err) return err } - // documents list - rows, err := postgres.Pool.Query(context.Background(), ` - SELECT - storage_attachment.id, - storage_attachment.service_name, - jsonb_agg( - jsonb_build_object( - 'id', storage_blob.id, - 'metadata', storage_blob.metadata, - 'filename', storage_blob.filename - ) - ) AS preview_images, - storage_attachment.created_at - FROM - "storage_attachment" - LEFT JOIN "storage_blob" ON "storage_attachment"."blob_id" = "storage_blob"."id" - WHERE - "storage_attachment"."record_type" = 'Template' - AND "storage_attachment"."name" = 'documents' - AND "storage_attachment"."record_id" = $1 - GROUP BY - storage_attachment.id - `, template) - if err != nil { - logging.Log.Err(err) - return err - } - defer rows.Close() - - for rows.Next() { - var serviceName string - document := &models.Document{} - previewImages := []models.PreviewImages{} - err := rows.Scan( - &document.ID, - &serviceName, - &previewImages, - &document.CreatedAt, - ) - if err != nil { - logging.Log.Err(err) - return err - } - - if serviceName == "disk" { - document.URL = "http://localhost:8088/drive/pages" - } - - if document.Metadata.Pdf.NumberOfPages == 0 { - document.Metadata.Pdf.NumberOfPages = 1 - } - document.PreviewImages = previewImages - - response.Documents = append(response.Documents, *document) - } - return webutil.Response(c, fiber.StatusOK, "Template", response) } diff --git a/internal/handlers/public/verify.go b/internal/handlers/public/verify.go index 67e6ec7..d1cbe0b 100644 --- a/internal/handlers/public/verify.go +++ b/internal/handlers/public/verify.go @@ -1,13 +1,18 @@ package handlers import ( + "context" + "encoding/hex" "fmt" "io" "os" + "strings" "github.com/gofiber/fiber/v2" + "github.com/jackc/pgx/v5" "github.com/shurco/gosign/internal/models" + "github.com/shurco/gosign/internal/queries" "github.com/shurco/gosign/pkg/pdf/verify" "github.com/shurco/gosign/pkg/utils/webutil" ) @@ -41,14 +46,17 @@ func VerifyPDF(c *fiber.Ctx) error { os.Remove(tempFile.Name()) }() - _, err = io.Copy(tempFile, file) - if err != nil { + if _, err := io.Copy(tempFile, file); err != nil { return webutil.StatusBadRequest(c, err.Error()) } verifyInfo, err := verify.File(tempFile) if err != nil { response.Error = err.Error() + return webutil.StatusOK(c, "Verify", response) + } + + if verifyInfo.Signers == nil { return webutil.Response(c, fiber.StatusOK, "Verify", response) } @@ -57,9 +65,11 @@ func VerifyPDF(c *fiber.Ctx) error { Name: value.Name, Reason: value.Reason, ValidSignature: value.ValidSignature, - TrustedIssuer: value.TrustedIssuer, + TrustedIssuer: models.TrustedIssuer{ + Valid: value.TrustedIssuer, + }, CertSubject: &models.CertSubject{ - Organisation: value.Certificates[0].Certificate.Subject.Organization, + Organization: value.Certificates[0].Certificate.Subject.Organization[0], CommonName: value.Certificates[0].Certificate.Subject.CommonName, }, RevokedCertificate: value.RevokedCertificate, @@ -70,17 +80,38 @@ func VerifyPDF(c *fiber.Ctx) error { Time: value.TimeStamp.Time.Unix(), } } + + // check in trusted base + if !value.TrustedIssuer { + for _, cert := range value.Certificates { + aki := cert.Certificate.AuthorityKeyId + trustCert, err := queries.DB.CheckAKI(context.Background(), strings.ToUpper(hex.EncodeToString(aki[:]))) + if err != nil && err != pgx.ErrNoRows { + return webutil.StatusInternalServerError(c) + } + fmt.Print(trustCert) + if trustCert != nil && trustCert.List != "" { + signer.TrustedIssuer = models.TrustedIssuer{ + Valid: true, + List: trustCert.List, + Name: trustCert.Name, + } + } + } + } + response.Signers = append(response.Signers, signer) } + response.Verify = true //response.Document = &Document{ // Creator: verifyInfo.DocumentInfo.Creator, // Hash: verifyInfo.DocumentInfo.Hash, //} - if verifyInfo.DocumentInfo.Creator == "goSign (https://github.com/shurco/goSign)" { - fmt.Print("check in database") - } + //if verifyInfo.DocumentInfo.Creator == "goSign (https://github.com/shurco/goSign)" { + // fmt.Print("check in database") + //} return webutil.Response(c, fiber.StatusOK, "Verify", response) } diff --git a/internal/models/sign.go b/internal/models/sign.go index 4ccb617..33b86d7 100644 --- a/internal/models/sign.go +++ b/internal/models/sign.go @@ -1,5 +1,6 @@ package models +// Sign is ... type Sign struct { Error string `json:"error,omitempty"` FileName string `json:"file_name,omitempty"` diff --git a/internal/models/template.go b/internal/models/template.go index 9b28226..4b95dd0 100644 --- a/internal/models/template.go +++ b/internal/models/template.go @@ -2,6 +2,7 @@ package models import "time" +// Template is ... type Template struct { ID string `json:"id"` FolderID string `json:"folder_id"` @@ -18,6 +19,7 @@ type Template struct { ArchivedAt *time.Time `json:"archived_at,omitempty"` } +// Author is ... type Author struct { ID string `json:"id"` FirstName string `json:"first_name"` @@ -25,11 +27,13 @@ type Author struct { Email string `json:"email"` } +// Submitter is ... type Submitter struct { ID string `json:"id"` Name string `json:"name"` } +// Field is ... type Field struct { ID string `json:"id"` SubmitterID string `json:"submitter_id"` @@ -39,6 +43,7 @@ type Field struct { Areas []*Areas `json:"areas,omitempty"` } +// Areas is ... type Areas struct { AttachmentID string `json:"attachment_id"` Page int `json:"page"` @@ -48,11 +53,13 @@ type Areas struct { H float64 `json:"z"` } +// Schema is ... type Schema struct { AttachmentID string `json:"attachment_id"` Name string `json:"name"` } +// Document is ... type Document struct { ID string `json:"id"` URL string `json:"url"` @@ -62,17 +69,20 @@ type Document struct { CreatedAt time.Time `json:"created_at"` } +// DocMetadata is ... type DocMetadata struct { Analyzed bool `json:"analyzed,omitempty"` Pdf Pdf `json:"pdf"` Sha256 string `json:"sha256,omitempty"` } +// Pdf os ... type Pdf struct { Annotations []*Annotations `json:"annotations,omitempty"` NumberOfPages int `json:"number_of_pages"` } +// Annotations is ... type Annotations struct { Type string `json:"type"` Value string `json:"value"` @@ -83,6 +93,7 @@ type Annotations struct { H float64 `json:"z"` } +// PreviewImages is ... type PreviewImages struct { ID string `json:"id"` RecordType string `json:"record_type,omitempty"` @@ -92,6 +103,7 @@ type PreviewImages struct { FileName string `json:"filename"` } +// ImgMetadata is ... type ImgMetadata struct { Analyzed bool `json:"analyzed,omitempty"` Identified bool `json:"identified,omitempty"` diff --git a/internal/models/user.go b/internal/models/user.go index 9e9319b..433ad03 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -10,6 +10,7 @@ const ( UserRoleAdmin ) +// User is ... type User struct { ID string `json:"id"` Name string `json:"name"` diff --git a/internal/models/verify.go b/internal/models/verify.go index a0cd6bf..57b4a13 100644 --- a/internal/models/verify.go +++ b/internal/models/verify.go @@ -1,5 +1,8 @@ package models +import "time" + +// Verify is ... type Verify struct { Verify bool `json:"verify"` Error string `json:"error,omitempty"` @@ -7,27 +10,52 @@ type Verify struct { Signers []*Signer `json:"signers"` } +// DocumentInfo is ... type DocumentInfo struct { Creator string `json:"creator"` Hash string `json:"hash"` } +// Signer is ... type Signer struct { - Name string `json:"name"` - Reason string `json:"reason"` - ValidSignature bool `json:"valid_signature"` - TrustedIssuer bool `json:"trusted_issuer"` - CertSubject *CertSubject `json:"cert_subject"` - SigFormat string `json:"sig_format"` - RevokedCertificate bool `json:"revoked_certificate"` - TimeStamp *TimeStamp `json:"time_stamp"` + Name string `json:"name"` + Reason string `json:"reason"` + ValidSignature bool `json:"valid_signature"` + TrustedIssuer TrustedIssuer `json:"trusted_issuer"` + CertSubject *CertSubject `json:"cert_subject"` + SigFormat string `json:"sig_format"` + RevokedCertificate bool `json:"revoked_certificate"` + TimeStamp *TimeStamp `json:"time_stamp"` +} + +// TrustedIssuer is ... +type TrustedIssuer struct { + Valid bool `json:"valid"` + List string `json:"list"` + Name string `json:"name"` } +// TimeStamp is ... type TimeStamp struct { Time int64 `json:"time"` } +// CertSubject is ... type CertSubject struct { - Organisation []string `json:"organisation"` - CommonName string `json:"common_name"` + Organization string `json:"organization"` + CommonName string `json:"common_name"` +} + +// TrustList is ... +type TrustCerts struct { + Certs []TrustCert `json:"trust_cert"` +} + +// TrustCert is ... +type TrustCert struct { + List string `json:"list"` + Name string `json:"name"` + AKI string `json:"aki"` + SKI string `json:"ski"` + CreatedAt *time.Time `json:"created,omitempty"` } diff --git a/internal/queries/queries.go b/internal/queries/queries.go new file mode 100644 index 0000000..6fb77c2 --- /dev/null +++ b/internal/queries/queries.go @@ -0,0 +1,85 @@ +package queries + +import ( + "context" + + "github.com/jackc/pgx/v5/pgxpool" + "github.com/jackc/pgx/v5/stdlib" + "github.com/pressly/goose/v3" + + "github.com/shurco/gosign/migrations" +) + +var DB *Base + +// Base is ... +type Base struct { + SystemQueries + TrustQueries + TemplateQueries +} + +// New is ... +func New(pool *pgxpool.Pool) error { + DB = &Base{ + SystemQueries: SystemQueries{pool}, + TrustQueries: TrustQueries{pool}, + TemplateQueries: TemplateQueries{pool}, + } + + return nil +} + +// Init is ... +func Init(pool *pgxpool.Pool) error { + New(pool) + + if _, err := pool.Query(context.Background(), `SELECT * FROM migrate_db_version`); err != nil { + goose.SetBaseFS(migrations.Embed()) + goose.SetTableName("migrate_db_version") + if err := goose.SetDialect("pgx"); err != nil { + return err + } + + db := stdlib.OpenDBFromPool(pool) + if err := goose.Up(db, "."); err != nil { + return err + } + } + + return nil +} + +/* +// SQLPagination is ... +// example query's for sortBy - id:DESC or id:ASC +func (db *Base) SQLPagination(params webutil.PaginationQuery) string { + if params.Offset < 0 { + params.Offset = 0 + } + + if params.Limit <= 0 { + params.Limit = 30 + } + + var showSortBy string + if len(params.SortBy) > 0 { + showSortBy = "ORDER BY " + + var orderParts []string + sorts := strings.Split(params.SortBy, ",") + for _, sort := range sorts { + parts := strings.SplitN(sort, ":", 2) + if len(parts) == 1 { + orderParts = append(orderParts, parts[0]) + } + if len(parts) == 2 { + orderParts = append(orderParts, fmt.Sprintf("%s %s", parts[0], parts[1])) + } + } + showSortBy = showSortBy + strings.Join(orderParts, ", ") + } + + return fmt.Sprintf(" %s LIMIT %d OFFSET %d", showSortBy, params.Limit, params.Offset) +} +*/ diff --git a/internal/queries/system.go b/internal/queries/system.go new file mode 100644 index 0000000..b550521 --- /dev/null +++ b/internal/queries/system.go @@ -0,0 +1,10 @@ +package queries + +import ( + "github.com/jackc/pgx/v5/pgxpool" +) + +// SystemQueries is ... +type SystemQueries struct { + *pgxpool.Pool +} diff --git a/internal/queries/template.go b/internal/queries/template.go new file mode 100644 index 0000000..81ab505 --- /dev/null +++ b/internal/queries/template.go @@ -0,0 +1,115 @@ +package queries + +import ( + "context" + + "github.com/jackc/pgx/v5/pgxpool" + + "github.com/shurco/gosign/internal/models" + "github.com/shurco/gosign/pkg/logging" +) + +// TemplateQueries is ... +type TemplateQueries struct { + *pgxpool.Pool +} + +// Template is ... +func (q *TemplateQueries) Template(ctx context.Context, id string) (*models.Template, error) { + template := &models.Template{} + + // template info + query := ` + SELECT + "template"."id", + "template"."slug", + "template"."name", + "template"."folder_id", + "template"."submitters", + "template"."fields", + "template"."schema", + "template"."created_at", + "template"."updated_at" + FROM + "template" + WHERE + "template"."id" = $1 + ` + err := q.QueryRow(ctx, query, id).Scan( + &template.ID, + &template.Slug, + &template.Name, + &template.FolderID, + &template.Submitters, + &template.Fields, + &template.Schema, + &template.CreatedAt, + &template.UpdatedAt, + ) + if err != nil { + logging.Log.Err(err) + return nil, err + } + + // documents list + query = ` + SELECT + "storage_attachment"."id", + "storage_attachment"."service_name", + jsonb_agg( + jsonb_build_object( + 'id', + storage_blob.id, + 'metadata', + storage_blob.metadata, + 'filename', + storage_blob.filename + ) + ) AS preview_images, + storage_attachment.created_at + FROM + "storage_attachment" + LEFT JOIN "storage_blob" ON "storage_attachment"."blob_id" = "storage_blob"."id" + WHERE + "storage_attachment"."record_type" = 'Template' + AND "storage_attachment"."name" = 'documents' + AND "storage_attachment"."record_id" = $1 + GROUP BY + storage_attachment.id + ` + rows, err := q.Query(ctx, query, id) + if err != nil { + logging.Log.Err(err) + return nil, err + } + defer rows.Close() + + for rows.Next() { + var serviceName string + document := &models.Document{} + previewImages := []models.PreviewImages{} + err := rows.Scan( + &document.ID, + &serviceName, + &previewImages, + &document.CreatedAt, + ) + if err != nil { + logging.Log.Err(err) + return nil, err + } + + if serviceName == "disk" { + document.URL = "http://localhost:8088/drive/pages" + } + + if document.Metadata.Pdf.NumberOfPages == 0 { + document.Metadata.Pdf.NumberOfPages = 1 + } + document.PreviewImages = previewImages + + template.Documents = append(template.Documents, *document) + } + + return template, nil +} diff --git a/internal/queries/trust.go b/internal/queries/trust.go new file mode 100644 index 0000000..b0ff388 --- /dev/null +++ b/internal/queries/trust.go @@ -0,0 +1,145 @@ +package queries + +import ( + "context" + "database/sql" + "time" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" + + "github.com/shurco/gosign/internal/models" +) + +// TrustQueries is ... +type TrustQueries struct { + *pgxpool.Pool +} + +// CheckAKI is ... +func (q *TrustQueries) CheckAKI(ctx context.Context, aki string) (*models.TrustCert, error) { + if aki == "" { + return nil, nil + } + + trustCert := &models.TrustCert{} + query := ` + SELECT + "list", + "name", + "aki", + "ski" + FROM + "trust_list" + WHERE + "ski" = $1 + LIMIT + 1 + ` + err := q.QueryRow(ctx, query, + aki, + ).Scan( + &trustCert.List, + &trustCert.Name, + &trustCert.AKI, + &trustCert.SKI, + ) + if err != nil { + return nil, err + } + + return trustCert, nil +} + +// AddAdobeTL is ... +func (q *TrustQueries) AddAdobeTL(ctx context.Context, trust models.TrustCerts) error { + var certsToInsert []models.TrustCert + + for _, v := range trust.Certs { + var aki string + query := ` + SELECT + "aki" + FROM + "trust_list" + WHERE + "aki" = $1 + LIMIT + 1 + ` + err := q.QueryRow(ctx, query, v.AKI).Scan(&aki) + if err != nil && err != pgx.ErrNoRows { + return err + } + if err == pgx.ErrNoRows { + certsToInsert = append(certsToInsert, v) + } + } + + if len(certsToInsert) > 0 { + batch := &pgx.Batch{} + insertQuery := ` + INSERT INTO + "trust_list" ("list", "name", "aki", "ski") + VALUES + ($1, $2, $3, $4) + ` + for _, cert := range certsToInsert { + batch.Queue(insertQuery, cert.List, cert.Name, cert.AKI, cert.SKI) + } + + br := q.SendBatch(ctx, batch) + defer br.Close() + + for range certsToInsert { + _, err := br.Exec() + if err != nil { + return err + } + } + } + + return nil +} + +// TimeUpdateAdobeTL is ... +func (q *TrustQueries) TimeUpdateAdobeTL(ctx context.Context) (*time.Time, error) { + var date sql.NullTime + query := ` + SELECT + MIN("created_at") AS "earliest_record" + FROM + "trust_list" + ` + if err := q.QueryRow(ctx, query).Scan(&date); err != nil { + return nil, err + } + + if date.Valid { + return &date.Time, nil + } + + return nil, nil +} + +// DeleteAdobeTL is ... +func (q *TrustQueries) DeleteAdobeTL(ctx context.Context, list string) error { + query := ` + DELETE FROM "trust_list" + WHERE + "list" = $1 + ` + _, err := q.Exec(ctx, query, list) + return err +} + +// ClearAdobeTL is ... +func (q *TrustQueries) ClearAdobeTL(ctx context.Context) error { + query := ` + DELETE FROM "trust_list" + WHERE + "list" != 'gosing' + ` + _, err := q.Exec(ctx, query) + return err +} diff --git a/internal/trust/trust.go b/internal/trust/trust.go new file mode 100644 index 0000000..21f196f --- /dev/null +++ b/internal/trust/trust.go @@ -0,0 +1,165 @@ +package trust + +import ( + "bytes" + "context" + "crypto/sha1" + "crypto/x509" + "encoding/base64" + "encoding/hex" + "encoding/xml" + "errors" + "fmt" + "io" + "net/http" + "os" + "strings" + "time" + + "github.com/pdfcpu/pdfcpu/pkg/api" + + "github.com/shurco/gosign/internal/models" + "github.com/shurco/gosign/internal/queries" + "github.com/shurco/gosign/pkg/utils/timeutil" +) + +// TrustList is ... +var TrustList = map[string]TrustEntry{ + "eutl12": { + Name: "Europe", + Url: "https://trustlist.adobe.com/eutl12.acrobatsecuritysettings", + }, + "tl12": { + Name: "Adobe", + Url: "https://trustlist.adobe.com/tl12.acrobatsecuritysettings", + }, +} + +// TrustEntry ... +type TrustEntry struct { + Name string + Url string +} + +// Config is ... +type Config struct { + List []string `toml:"list"` + Update int `toml:"update-frequency"` +} + +// SecuritySettings is ... +type SecuritySettings struct { + TrustedIdentities struct { + Identity []struct { + ImportAction int `xml:"ImportAction"` + Certificate string `xml:"Certificate"` + } `xml:"Identity"` + } `xml:"TrustedIdentities"` +} + +// Update is ... +func Update(cfg Config) error { + dateUp, err := queries.DB.TimeUpdateAdobeTL(context.Background()) + if err != nil { + return err + } + + daysDiff := 999 + if dateUp != nil { + daysDiff = timeutil.DaysBetween(*dateUp, time.Now()) + } + + if daysDiff < cfg.Update { + return nil + } + + fmt.Printf("├─[🌍] Updating the list of trusted Adobe certificates\n") + for _, v := range cfg.List { + trust, found := TrustList[v] + if !found { + return errors.New("not found trust list") + } + err := parseTL(v, trust.Url) + if err != nil { + return err + } + } + + return nil +} + +func parseTL(list, url string) error { + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Get(url) + if err != nil { + return errors.New("error fetching security settings") + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return errors.New("received non-OK HTTP status code") + } + + data, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + securityFile := "SecuritySettings.xml" + if err := api.ExtractAttachments(bytes.NewReader(data), "./", []string{securityFile}, nil); err != nil { + return errors.New("error extracting attachments") + } + + fileContents, err := os.ReadFile("./" + securityFile) + if err != nil { + return errors.New("error opening file") + } + + var securitySettings SecuritySettings + err = xml.Unmarshal(fileContents, &securitySettings) + if err != nil { + return errors.New("error decoding XML") + } + + trustList := models.TrustCerts{} + for _, identity := range securitySettings.TrustedIdentities.Identity { + decodedData, err := base64.StdEncoding.DecodeString(identity.Certificate) + if err != nil { + return errors.New("error decoding certificate") + } + + cert, err := x509.ParseCertificate(decodedData) + if err != nil { + //if err.Error() == "x509: unsupported elliptic curve" { + // fmt.Printf("elliptic\n") + // continue + //} + //fmt.Printf("error parsing certificate: %s\n", err) + //log.Warn().Err(err).Send() + continue + } + + akiHash := sha1.Sum(decodedData) + trustCert := models.TrustCert{ + List: list, + Name: cert.Subject.CommonName, + AKI: strings.ToUpper(hex.EncodeToString(akiHash[:])), + SKI: strings.ToUpper(hex.EncodeToString(cert.SubjectKeyId[:])), + } + + trustList.Certs = append(trustList.Certs, trustCert) + } + + if err := queries.DB.DeleteAdobeTL(context.Background(), list); err != nil { + return err + } + + if err := queries.DB.AddAdobeTL(context.Background(), trustList); err != nil { + return err + } + + if err := os.Remove("./" + securityFile); err != nil { + return errors.New("error removing file") + } + return nil +} diff --git a/migrations/20240108201452_init_table.sql b/migrations/20240108201452_init_table.sql index 3d8b998..ebfaa4b 100644 --- a/migrations/20240108201452_init_table.sql +++ b/migrations/20240108201452_init_table.sql @@ -150,10 +150,20 @@ CREATE TABLE "public"."country" ( "name" varchar(255) NOT NULL, PRIMARY KEY ("code") ); + +CREATE TABLE "public"."trust_list" ( + "list" varchar(10) NOT NULL, + "name" varchar NOT NULL, + "aki" varchar NOT NULL, + "ski" varchar NOT NULL, + "created_at" timestamp DEFAULT NOW() +); +CREATE INDEX "trust_list_aki" ON "public"."trust_list" USING BTREE ("aki"); -- +goose StatementEnd -- +goose Down -- +goose StatementBegin +DROP TABLE IF EXISTS "trust_list"; DROP TABLE IF EXISTS "country"; DROP TABLE IF EXISTS "storage_attachment"; DROP TABLE IF EXISTS "storage_blob"; diff --git a/migrations/embed.go b/migrations/embed.go new file mode 100644 index 0000000..a06e71e --- /dev/null +++ b/migrations/embed.go @@ -0,0 +1,11 @@ +package migrations + +import "embed" + +//go:embed *.sql +var migrations embed.FS + +// Embed is ... +func Embed() embed.FS { + return migrations +} diff --git a/pkg/config/config.go b/pkg/config/config.go deleted file mode 100644 index b40bca2..0000000 --- a/pkg/config/config.go +++ /dev/null @@ -1,84 +0,0 @@ -package config - -import ( - "fmt" - "os" - "strconv" - "time" - - "github.com/shurco/gosign/pkg/utils/strutil" -) - -func lookup(key string, fallback string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return fallback -} - -// GetString is ... -func GetString(key, fallback string) string { - return lookup(key, fallback) -} - -// GetSliceString is ... -func GetSliceString(key, fallback string) []string { - value := lookup(key, fallback) - return strutil.ToSlice(value) -} - -// GetInt is ... -func GetInt(key string, fallback int) int { - value := lookup(key, "") - if value, err := strconv.Atoi(value); err == nil { - return value - } - return fallback -} - -// GetInt32 is ... -func GetInt32(key string, fallback int32) int32 { - value := lookup(key, "") - if value, err := strconv.ParseInt(value, 10, 32); err == nil { - return int32(value) - } - return fallback -} - -// GetBool is ... -func GetBool(key string, fallback bool) bool { - value := lookup(key, "") - if value, err := strconv.ParseBool(value); err == nil { - return value - } - return fallback -} - -// GetDuration is ... -func GetDuration(key, fallback string) time.Duration { - value := lookup(key, fallback) - duration, _ := time.ParseDuration(value) - return duration -} - -// GetByteFromFile is ... -func GetByteFromFile(key, fallback string) ([]byte, error) { - var data []byte - value := lookup(key, fallback) - - // Simplify the if condition by handling the error directly from 'readFile' - var err error - if data, err = readFile(value); err != nil { - return nil, fmt.Errorf("failed to read %q: %w", value, err) - } - - return data, nil -} - -func readFile(file string) ([]byte, error) { - data, err := os.ReadFile(file) - if err != nil { - return nil, fmt.Errorf("failed to read file %s: %w", file, err) - } - return data, nil -} diff --git a/pkg/pdf/verify/verify.go b/pkg/pdf/verify/verify.go index 3d0bfb1..fdbe6f5 100644 --- a/pkg/pdf/verify/verify.go +++ b/pkg/pdf/verify/verify.go @@ -24,8 +24,8 @@ import ( ) var ( - ErrNoSignatire = errors.New("No digital signature in document") - ErrNoResultWithSignatire = errors.New("Document looks to have a signature but got no results") + ErrNoSignature = errors.New("no digital signature in document") + ErrNoResultWithSignature = errors.New("document looks to have a signature but got no results") ) type Response struct { @@ -75,12 +75,12 @@ type DocumentInfo struct { } func File(file *os.File) (apiResp *Response, err error) { - finfo, _ := file.Stat() + info, _ := file.Stat() if _, err := file.Seek(0, 0); err != nil { return nil, err } - return Reader(file, finfo.Size()) + return Reader(file, info.Size()) } func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { @@ -97,13 +97,13 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { rdr, err := pdf.NewReader(file, size) if err != nil { - return nil, fmt.Errorf("Failed to open file: %v", err) + return nil, fmt.Errorf("failed to open file: %v", err) } // AcroForm will contain a SigFlags value if the form contains a digital signature t := rdr.Trailer().Key("Root").Key("AcroForm").Key("SigFlags") if t.IsNull() { - return nil, ErrNoSignatire + return nil, ErrNoSignature } // Walk over the cross references in the document @@ -180,8 +180,6 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { // fmt.Printf("U: %v, %#v\n", s.IssuerAndSerialNumber.SerialNumber, attr.Type) if attr.Type.Equal(asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14}) { - // fmt.Println("Found timestamp") - signer.TimeStamp, err = timestamp.Parse(attr.Value.Bytes) if err != nil { apiResp.Error = fmt.Sprintln("Failed to parse timestamp", err) @@ -215,10 +213,8 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { } // Verify the digital signature of the pdf file. - err = p7.VerifyWithChain(certPool) - if err != nil { - err = p7.Verify() - if err == nil { + if err := p7.VerifyWithChain(certPool); err != nil { + if err := p7.Verify(); err == nil { signer.ValidSignature = true signer.TrustedIssuer = false } else { @@ -330,7 +326,7 @@ func Reader(file io.ReaderAt, size int64) (apiResp *Response, err error) { } if apiResp == nil { - err = ErrNoResultWithSignatire + err = ErrNoResultWithSignature } apiResp.DocumentInfo = documentInfo diff --git a/pkg/storage/postgres/postgres.go b/pkg/storage/postgres/postgres.go index 225e7c6..50110ca 100644 --- a/pkg/storage/postgres/postgres.go +++ b/pkg/storage/postgres/postgres.go @@ -4,41 +4,38 @@ import ( "context" "database/sql" "fmt" - "time" // Load jackc package + "github.com/jackc/pgx/v5/pgxpool" _ "github.com/jackc/pgx/v5/stdlib" ) var Client *sql.DB -// PgSQLConfig is ... -type PgSQLConfig struct { - DSN string - MaxConn int - MaxIdleConn int - MaxLifetimeConn int +// Config is ... +type Config struct { + URL string `toml:"url"` } -var Pool *pgxpool.Pool +// New creates a new Connect object using the given PgSQLConfig. +func New(ctx context.Context, conf Config) (*pgxpool.Pool, error) { + // ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + // defer cancel() + + config, _ := pgxpool.ParseConfig(conf.URL) + // config.MaxConnLifetime = time.Duration(conf.MaxLifetimeConn) * time.Second -// NewClient creates a new Connect object using the given PgSQLConfig. -func NewClient(ctx context.Context, conf *PgSQLConfig) error { - p, err := pgxpool.New(ctx, conf.DSN) + pool, err := pgxpool.NewWithConfig(ctx, config) if err != nil { - return err + return nil, err } + // defer pool.Close() // Ping the database to ensure connectivity. - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - if err := p.Ping(ctx); err != nil { - return fmt.Errorf("could not ping database: %v", err) + if err := pool.Ping(ctx); err != nil { + return nil, fmt.Errorf("could not ping database: %v", err) } - Pool = p - - // Return the new Connect object. - return nil + return pool, nil } diff --git a/pkg/storage/redis/redis.go b/pkg/storage/redis/redis.go index b98aee2..fb738be 100644 --- a/pkg/storage/redis/redis.go +++ b/pkg/storage/redis/redis.go @@ -9,6 +9,12 @@ import ( var Conn Handler +// Config is ... +type Config struct { + Address string `toml:"address"` + Password string `toml:"password"` +} + // Handler is ... type Handler interface { Close() error @@ -26,8 +32,8 @@ type rdb struct { client *redis.Client } -// NewClient creates a new Handler backed by Redis using the given options. -func NewClient(ctx context.Context, addr, password string) Handler { +// New creates a new Handler backed by Redis using the given options. +func New(ctx context.Context, addr, password string) Handler { Conn = &rdb{ ctx: ctx, client: redis.NewClient(&redis.Options{ @@ -51,8 +57,7 @@ func (c rdb) Ping() error { // Set is provides a way to set values in Redis. func (c rdb) Set(key string, value any, expiration time.Duration) error { - err := c.client.Set(c.ctx, key, value, expiration).Err() - return err + return c.client.Set(c.ctx, key, value, expiration).Err() } // Get is provides a way to retrieve values from Redis. diff --git a/pkg/utils/timeutil/time.go b/pkg/utils/timeutil/time.go new file mode 100644 index 0000000..afb77da --- /dev/null +++ b/pkg/utils/timeutil/time.go @@ -0,0 +1,18 @@ +package timeutil + +import "time" + +// IsToday is ... +func IsToday(t time.Time) bool { + now := time.Now().Truncate(24 * time.Hour) + t = t.Truncate(24 * time.Hour) + return now.Equal(t) +} + +// DaysBetween is ... +func DaysBetween(start, end time.Time) int { + start = start.Truncate(24 * time.Hour) + end = end.Truncate(24 * time.Hour) + duration := end.Sub(start) + return int(duration.Hours() / 24) +} diff --git a/pkg/utils/webutil/pagination.go b/pkg/utils/webutil/pagination.go new file mode 100644 index 0000000..fb09a3a --- /dev/null +++ b/pkg/utils/webutil/pagination.go @@ -0,0 +1,59 @@ +package webutil + +import ( + "fmt" + "math" + + "github.com/gofiber/fiber/v2" + + "github.com/shurco/gosign/pkg/utils/strutil" +) + +const defaultLimit int32 = 10 // Use const instead of var for constants. + +// PaginationQuery represents pagination parameters. +type PaginationQuery struct { + Limit int32 `json:"limit" form:"limit"` + Offset int32 `json:"offset" form:"offset"` + SortBy string `json:"sort_by" form:"sort_by"` // Corrected typo in form tag. +} + +// GetPaginationFromCtx creates a PaginationQuery from the fiber context. +func GetPaginationFromCtx(c *fiber.Ctx) *PaginationQuery { + return &PaginationQuery{ + Limit: parseOrDefault(c.Query("limit"), defaultLimit), + Offset: parseOrDefault(c.Query("offset"), 0), + SortBy: c.Query("sort_by"), + } +} + +// parseOrDefault tries to parse an int32 value from the query parameter or returns the default value. +func parseOrDefault(queryParam string, defaultValue int32) int32 { + if queryParam == "" { + return defaultValue + } + + value := strutil.ToInt32(queryParam) + return value +} + +// GetQueryString constructs a query string with the pagination parameters. +func (p *PaginationQuery) GetQueryString() string { + return fmt.Sprintf("limit=%d&offset=%d", p.Limit, p.Offset) +} + +// GetSelectPage calculates the current page based on offset and limit. +func (p *PaginationQuery) GetSelectPage() int32 { + if p.Limit == 0 { + return 0 + } + return p.Offset / p.Limit +} + +// GetTotalPages calculates the total number of pages based on total records. +func (p *PaginationQuery) GetTotalPages(totalRecords int32) int32 { + if p.Limit == 0 { + return 0 + } + return int32(math.Ceil(float64(totalRecords) / float64(p.Limit))) +} diff --git a/scripts/migration b/scripts/migration index c38daf1..5d8ae3f 100755 --- a/scripts/migration +++ b/scripts/migration @@ -81,13 +81,21 @@ elif [[ $MIGRATION == "dev" ]]; then arr_goose=(up down reset) if [[ " ${arr_goose[*]} " =~ " $GOOSE_ACTION " ]]; then SOURCE=${BASH_SOURCE[0]} - if [ $GOOSE_ACTION == "up" ]; then - mkdir -p "${LC_PAGES_DIR}" - cp -R ${ROOT_PATH}/fixtures/pages/* ${LC_PAGES_DIR} - mkdir -p "${LC_SIGNED_DIR}" - cp -R ${ROOT_PATH}/fixtures/signed/* ${LC_SIGNED_DIR} - mkdir -p "${LC_UPLOADS_DIR}" - cp -R ${ROOT_PATH}/fixtures/uploads/* ${LC_UPLOADS_DIR} + if [ $GOOSE_ACTION == "up" ]; then + declare -A FIXTURES_MAP=( + ["pages"]="${LC_PAGES_DIR}" + ["signed"]="${LC_SIGNED_DIR}" + ["uploads"]="${LC_UPLOADS_DIR}" + ) + + for fixture in "${!FIXTURES_MAP[@]}"; do + src_dir="${ROOT_PATH}/fixtures/${fixture}/" + dest_dir="${FIXTURES_MAP[$fixture]}" + mkdir -p "${dest_dir}" + if [ "$(ls -A "${src_dir}")" ]; then + cp -R "${src_dir}"* "${dest_dir}" + fi + done $SOURCE up $SOURCE test up @@ -125,4 +133,4 @@ elif [[ $MIGRATION == "dev" ]]; then else print_header "Migrations sql" run_goose $MIGRATION -fi \ No newline at end of file +fi diff --git a/web/package.json b/web/package.json index dfb7afe..f838de4 100644 --- a/web/package.json +++ b/web/package.json @@ -16,9 +16,9 @@ "pinia": "^2.1.7", "signature_pad": "^4.2.0", "uuid": "^9.0.1", - "volar-service-prettier": "^0.0.34", - "vue": "^3.4.22", - "vue-router": "^4.3.0" + "volar-service-prettier": "^0.0.42", + "vue": "^3.4.26", + "vue-router": "^4.3.2" }, "devDependencies": { "@tsconfig/node18": "^18.2.4", @@ -30,13 +30,13 @@ "npm-run-all2": "^6.1.2", "postcss": "^8.4.38", "postcss-import": "^16.1.0", - "postcss-nesting": "^12.1.1", + "postcss-nesting": "^12.1.2", "prettier": "^3.2.5", "tailwindcss": "^3.4.3", "typescript": "~5.4.5", - "vite": "^5.2.9", + "vite": "^5.2.10", "vite-plugin-svg-icons": "^2.0.1", - "vite-plugin-vue-devtools": "^7.0.27", - "vue-tsc": "^2.0.13" + "vite-plugin-vue-devtools": "^7.1.3", + "vue-tsc": "^2.0.16" } } diff --git a/web/src/models/index.ts b/web/src/models/index.ts index b50d1cb..30b5e94 100644 --- a/web/src/models/index.ts +++ b/web/src/models/index.ts @@ -153,6 +153,6 @@ export interface TimeStamp { time: number /* int64 */; } export interface CertSubject { - organisation: string[]; + organization: string[]; common_name: string; } diff --git a/web/src/pages/Verify.vue b/web/src/pages/Verify.vue index a333f81..6f1b33d 100644 --- a/web/src/pages/Verify.vue +++ b/web/src/pages/Verify.vue @@ -41,18 +41,17 @@
- + Signature valid
- - - Timestamp + + Timestamp
- + Trusted issuer
@@ -63,15 +62,6 @@ Active certificate
-
- - - - - - Signed with external certificate -
-
{{ item.name ? item.name : item.reason }} @@ -84,7 +74,7 @@
- {{ item.cert_subject.common_name ? item.cert_subject.common_name : item.cert_subject.organisation[0] }} + {{ item.cert_subject.common_name ? item.cert_subject.common_name : item.cert_subject.organization }}
diff --git a/web/yarn.lock b/web/yarn.lock index bd749ee..4f5b2ad 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -222,7 +222,7 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== -"@babel/parser@^7.24.1": +"@babel/parser@^7.24.1", "@babel/parser@^7.24.4": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88" integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg== @@ -648,26 +648,26 @@ resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37" integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ== -"@volar/language-core@2.2.0-alpha.8": - version "2.2.0-alpha.8" - resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.2.0-alpha.8.tgz#74120a27ff2498ad297e86d17be95a9c7e1b46f5" - integrity sha512-Ew1Iw7/RIRNuDLn60fWJdOLApAlfTVPxbPiSLzc434PReC9kleYtaa//Wo2WlN1oiRqneW0pWQQV0CwYqaimLQ== +"@volar/language-core@2.2.0", "@volar/language-core@~2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.2.0.tgz#f6049ed29d356dac06f85d8b013469d514640baf" + integrity sha512-a8WG9+4OdeNDW4ywABZIM6S6UN7em8uIlM/BZ2pWQUYrVmX+m8sj/X+QadvO+Li/t/LjAqbWJQtVgxdpEWLALQ== dependencies: - "@volar/source-map" "2.2.0-alpha.8" + "@volar/source-map" "2.2.0" -"@volar/source-map@2.2.0-alpha.8": - version "2.2.0-alpha.8" - resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.2.0-alpha.8.tgz#ca090f828fbef7e09ea06a636c41a06aa2afe153" - integrity sha512-E1ZVmXFJ5DU4fWDcWHzi8OLqqReqIDwhXvIMhVdk6+VipfMVv4SkryXu7/rs4GA/GsebcRyJdaSkKBB3OAkIcA== +"@volar/source-map@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.2.0.tgz#9d9947ce64396290d80a15d692cc35003c5613c3" + integrity sha512-HQlPRlHOVqCCHK8wI76ZldHkEwKsjp7E6idUc36Ekni+KJDNrqgSqPvyHQixybXPHNU7CI9Uxd9/IkxO7LuNBw== dependencies: muggle-string "^0.4.0" -"@volar/typescript@2.2.0-alpha.8": - version "2.2.0-alpha.8" - resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.2.0-alpha.8.tgz#83a056c52995b4142364be3dda41d955a96f7356" - integrity sha512-RLbRDI+17CiayHZs9HhSzlH0FhLl/+XK6o2qoiw2o2GGKcyD1aDoY6AcMd44acYncTOrqoTNoY6LuCiRyiJiGg== +"@volar/typescript@~2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.2.0.tgz#826a901cefbe9f6c2ca295291eab48ed3eaeef80" + integrity sha512-wC6l4zLiiCLxF+FGaHCbWlQYf4vMsnRxYhcI6WgvaNppOD6r1g+Ef1RKRJUApALWU46Yy/JDU/TbdV6w/X6Liw== dependencies: - "@volar/language-core" "2.2.0-alpha.8" + "@volar/language-core" "2.2.0" path-browserify "^1.0.1" "@vue/babel-helper-vue-transform-on@^1.1.6": @@ -701,7 +701,26 @@ estree-walker "^2.0.2" source-map-js "^1.2.0" -"@vue/compiler-dom@3.4.22", "@vue/compiler-dom@^3.3.4", "@vue/compiler-dom@^3.4.0": +"@vue/compiler-core@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.26.tgz#d507886520e83a6f8339ed55ed0b2b5d84b44b73" + integrity sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ== + dependencies: + "@babel/parser" "^7.24.4" + "@vue/shared" "3.4.26" + entities "^4.5.0" + estree-walker "^2.0.2" + source-map-js "^1.2.0" + +"@vue/compiler-dom@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.26.tgz#acc7b788b48152d087d4bb9e655b795e3dbec554" + integrity sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA== + dependencies: + "@vue/compiler-core" "3.4.26" + "@vue/shared" "3.4.26" + +"@vue/compiler-dom@^3.3.4", "@vue/compiler-dom@^3.4.0": version "3.4.22" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.22.tgz#e628fb3774d07229817400a107f2ed036ecfc43e" integrity sha512-YkAS+jZc6Ip360kT3lZbMQZteiYBbHDSVKr94Jdd8Zjr7VjSkkXKAFFR/FW+2tNtBYXOps6xrWlOquy3GeYB0w== @@ -709,28 +728,28 @@ "@vue/compiler-core" "3.4.22" "@vue/shared" "3.4.22" -"@vue/compiler-sfc@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.22.tgz#699cf372c8fff4bab6003dd9d4c50ba379242c99" - integrity sha512-Pncp5Vc8E2Ef1o5uveO8WA1IqM7rt0R1jN8D4qitQYOUxC97iITGYA8oMInQ3UcDS7ip+SegyA2HbAEB4V6NMQ== +"@vue/compiler-sfc@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.26.tgz#c679f206829954c3c078d8a9be76d0098b8377ae" + integrity sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw== dependencies: - "@babel/parser" "^7.24.1" - "@vue/compiler-core" "3.4.22" - "@vue/compiler-dom" "3.4.22" - "@vue/compiler-ssr" "3.4.22" - "@vue/shared" "3.4.22" + "@babel/parser" "^7.24.4" + "@vue/compiler-core" "3.4.26" + "@vue/compiler-dom" "3.4.26" + "@vue/compiler-ssr" "3.4.26" + "@vue/shared" "3.4.26" estree-walker "^2.0.2" - magic-string "^0.30.8" + magic-string "^0.30.10" postcss "^8.4.38" source-map-js "^1.2.0" -"@vue/compiler-ssr@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.22.tgz#b84127c159a887bff1b7e2ab5c8ec41a759edb06" - integrity sha512-ycb2sL0SW6AkgVMrvaU/TIAEk7FQWyv/oYya44E/V9xURM+ij9Oev5bVobSS7GLJzkUieWW3SrYcK/PZpb5i4A== +"@vue/compiler-ssr@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.26.tgz#22842d8adfff972d87bb798b8d496111f7f814b5" + integrity sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ== dependencies: - "@vue/compiler-dom" "3.4.22" - "@vue/shared" "3.4.22" + "@vue/compiler-dom" "3.4.26" + "@vue/shared" "3.4.26" "@vue/devtools-api@^6.5.0": version "6.5.1" @@ -742,42 +761,42 @@ resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.1.tgz#7c14346383751d9f6ad4bea0963245b30220ef83" integrity sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA== -"@vue/devtools-core@^7.0.27": - version "7.0.27" - resolved "https://registry.yarnpkg.com/@vue/devtools-core/-/devtools-core-7.0.27.tgz#a3fd91deb08922e64a7253bf784c953e64e74fb8" - integrity sha512-3rbtNGxFFFPfIObgTAPIw0h0rJy+y1PrbfgM9nXRf3/FIJkthfS19yj31pj9EWIqRsyiqK5u1Ni7SAJZ0vsQOA== +"@vue/devtools-core@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@vue/devtools-core/-/devtools-core-7.1.3.tgz#22107b618ae05d873545724c6238a8c41c70b426" + integrity sha512-pVbWi8pf2Z/fZPioYOIgu+cv9pQG55k4D8bL31ec+Wfe+pQR0ImFDu0OhHfch1Ra8uvLLrAZTF4IKeGAkmzD4A== dependencies: - "@vue/devtools-kit" "^7.0.27" - "@vue/devtools-shared" "^7.0.27" + "@vue/devtools-kit" "^7.1.3" + "@vue/devtools-shared" "^7.1.3" mitt "^3.0.1" nanoid "^3.3.4" pathe "^1.1.2" vite-hot-client "^0.2.3" -"@vue/devtools-kit@^7.0.27": - version "7.0.27" - resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-7.0.27.tgz#23dfcc70da74291f5ec5456cc8a4644093b6045f" - integrity sha512-/A5xM38pPCFX5Yhl/lRFAzjyK6VNsH670nww2WbjFKWqlu3I+lMxWKzQkCW6A1V8bduITgl2kHORfg2gTw6QaA== +"@vue/devtools-kit@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@vue/devtools-kit/-/devtools-kit-7.1.3.tgz#0344fd1a926ff535d3be3378e1da8bb71d8430b9" + integrity sha512-NFskFSJMVCBXTkByuk2llzI3KD3Blcm7WqiRorWjD6nClHPgkH5BobDH08rfulqq5ocRt5xV+3qOT1Q9FXJrwQ== dependencies: - "@vue/devtools-shared" "^7.0.27" + "@vue/devtools-shared" "^7.1.3" hookable "^5.5.3" mitt "^3.0.1" perfect-debounce "^1.0.0" speakingurl "^14.0.1" -"@vue/devtools-shared@^7.0.27": - version "7.0.27" - resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-7.0.27.tgz#99d6d64f502110bb4b20a4029029a16ea62ed837" - integrity sha512-4VxtmZ6yjhiSloqZZq2UYU0TBGxOJ8GxWvp5OlAH70zYqi0FIAyWGPkOhvfoZ7DKQyv2UU0mmKzFHjsEkelGyQ== +"@vue/devtools-shared@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@vue/devtools-shared/-/devtools-shared-7.1.3.tgz#f570bba72d53a0c84d1faa19f4d1a29a339c1dc7" + integrity sha512-KJ3AfgjTn3tJz/XKF+BlVShNPecim3G21oHRue+YQOsooW+0s+qXvm09U09aO7yBza5SivL1QgxSrzAbiKWjhQ== dependencies: rfdc "^1.3.1" -"@vue/language-core@2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.13.tgz#2d1638b882011187b4b57115425d52b0901acab5" - integrity sha512-oQgM+BM66SU5GKtUMLQSQN0bxHFkFpLSSAiY87wVziPaiNQZuKVDt/3yA7GB9PiQw0y/bTNL0bOc0jM/siYjKg== +"@vue/language-core@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.16.tgz#c059228e6a0a17b4505421da0e5747a4a04facbe" + integrity sha512-Bc2sexRH99pznOph8mLw2BlRZ9edm7tW51kcBXgx8adAoOcZUWJj3UNSsdQ6H9Y8meGz7BoazVrVo/jUukIsPw== dependencies: - "@volar/language-core" "2.2.0-alpha.8" + "@volar/language-core" "~2.2.0" "@vue/compiler-dom" "^3.4.0" "@vue/shared" "^3.4.0" computeds "^0.0.1" @@ -785,43 +804,48 @@ path-browserify "^1.0.1" vue-template-compiler "^2.7.14" -"@vue/reactivity@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.22.tgz#5e83b6505b4d8382de5a9231e903599675d121cb" - integrity sha512-+golHRRfcGoahBrhoTauFNIIAhxntRV3BI8HHqVvCdsuWivxW1MI0E9AOXVsz4H/ZlWM1ahudWTX6PhUrNR2yQ== +"@vue/reactivity@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.26.tgz#1191f543809d4c93e5b3e842ba83022350a3f205" + integrity sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ== dependencies: - "@vue/shared" "3.4.22" + "@vue/shared" "3.4.26" -"@vue/runtime-core@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.22.tgz#924ca0c933945c8e8822281a6140fae967813db9" - integrity sha512-cbA8lcL4g1907EdY1a1KmP5IRWfbqjgBRcgJPkF//yn96XSC1/VAJBZiAGLiyw0P77Rw2Ao7d9U51vU1GC6yUQ== +"@vue/runtime-core@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.26.tgz#51ee971cb700370a67e5a510c4a84eff7491d658" + integrity sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw== dependencies: - "@vue/reactivity" "3.4.22" - "@vue/shared" "3.4.22" + "@vue/reactivity" "3.4.26" + "@vue/shared" "3.4.26" -"@vue/runtime-dom@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.22.tgz#704e67c2bbf0cdb0c87dfe8d04a6cbc9709f5b9f" - integrity sha512-AXxRHrFkLX1y2+70CO2wDKRxW0WZcQKTOXS31AK+jZ1RLPtI6sEHVpYNfyE9WgbgXOqPtX4gfIfuoFYi8iCu2w== +"@vue/runtime-dom@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.26.tgz#179aa7c8dc964112e6d096bc8ec5f361111009a1" + integrity sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw== dependencies: - "@vue/runtime-core" "3.4.22" - "@vue/shared" "3.4.22" + "@vue/runtime-core" "3.4.26" + "@vue/shared" "3.4.26" csstype "^3.1.3" -"@vue/server-renderer@3.4.22": - version "3.4.22" - resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.22.tgz#bd0bf0f7bf3366d214b7407cfd3a8451b084ce58" - integrity sha512-okiNxiCOhJlx6IOrTZvhIVwf2UYKay0hnIPqWu4h19bkNv1gmG4Ic6U3zXY287AWF26lQuFMa515Qzc+R0aAYg== +"@vue/server-renderer@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.26.tgz#6d0c6b0366bfe0232579aea00e3ff6784e5a1c60" + integrity sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw== dependencies: - "@vue/compiler-ssr" "3.4.22" - "@vue/shared" "3.4.22" + "@vue/compiler-ssr" "3.4.26" + "@vue/shared" "3.4.26" "@vue/shared@3.4.22", "@vue/shared@^3.4.0": version "3.4.22" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.22.tgz#74ef61b66a129905f84dce2e58b901208368af1e" integrity sha512-cg7R9XNk4ovV3bKka/1a464O2oY0l5Fyt0rwGR4hSJRPjUJ0WVjrPdsr4W0JbUriwiM8EKcCcCjeKN5pRMs2Zg== +"@vue/shared@3.4.26": + version "3.4.26" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.26.tgz#f17854fb1faf889854aed4b23b60e86a8cab6403" + integrity sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ== + "@vue/tsconfig@^0.5.1": version "0.5.1" resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.5.1.tgz#3124ec16cc0c7e04165b88dc091e6b97782fffa9" @@ -2034,6 +2058,13 @@ lru-cache@^6.0.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== +magic-string@^0.30.10: + version "0.30.10" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" + integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + magic-string@^0.30.4: version "0.30.5" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" @@ -2041,13 +2072,6 @@ magic-string@^0.30.4: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.8: - version "0.30.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.9.tgz#8927ae21bfdd856310e07a1bc8dd5e73cb6c251d" - integrity sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -2292,10 +2316,10 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" -open@^10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/open/-/open-10.0.3.tgz#f60d8db49fa126c50aec751957fb5d7de3308d4f" - integrity sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A== +open@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== dependencies: default-browser "^5.2.1" define-lazy-prop "^3.0.0" @@ -2428,10 +2452,10 @@ postcss-nested@^6.0.1: dependencies: postcss-selector-parser "^6.0.11" -postcss-nesting@^12.1.1: - version "12.1.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-12.1.1.tgz#6662d9c70e6356686dc24132f2a7520ec90d39ef" - integrity sha512-qc74KvIAQNa5ujZKG1UV286dhaDW6basbUy2i9AzNU/T8C9hpvGu9NZzm1SfePe2yP7sPYgpA8d4sPVopn2Hhw== +postcss-nesting@^12.1.2: + version "12.1.2" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-12.1.2.tgz#e7aba3f73b86a0e944e84798d481b54dcfce802e" + integrity sha512-FUmTHGDNundodutB4PUBxt/EPuhgtpk8FJGRsBhOuy+6FnkR2A8RZWIsyyy6XmhvX2DZQQWIkvu+HB4IbJm+Ew== dependencies: "@csstools/selector-resolve-nested" "^1.1.0" "@csstools/selector-specificity" "^3.0.3" @@ -3103,17 +3127,17 @@ vite-hot-client@^0.2.3: resolved "https://registry.yarnpkg.com/vite-hot-client/-/vite-hot-client-0.2.3.tgz#db52aba46edbcfa7906dbca8255fd35b9a9270b2" integrity sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg== -vite-plugin-inspect@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/vite-plugin-inspect/-/vite-plugin-inspect-0.8.3.tgz#06ff565f1df84f2ce607007493301579d288cf60" - integrity sha512-SBVzOIdP/kwe6hjkt7LSW4D0+REqqe58AumcnCfRNw4Kt3mbS9pEBkch+nupu2PBxv2tQi69EQHQ1ZA1vgB/Og== +vite-plugin-inspect@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/vite-plugin-inspect/-/vite-plugin-inspect-0.8.4.tgz#1fcdf6703164d651db3f13c8c6610e1ced5108e1" + integrity sha512-G0N3rjfw+AiiwnGw50KlObIHYWfulVwaCBUBLh2xTW9G1eM9ocE5olXkEYUbwyTmX+azM8duubi+9w5awdCz+g== dependencies: "@antfu/utils" "^0.7.7" "@rollup/pluginutils" "^5.1.0" debug "^4.3.4" error-stack-parser-es "^0.1.1" fs-extra "^11.2.0" - open "^10.0.3" + open "^10.1.0" perfect-debounce "^1.0.0" picocolors "^1.0.0" sirv "^2.0.4" @@ -3132,23 +3156,23 @@ vite-plugin-svg-icons@^2.0.1: svg-baker "1.7.0" svgo "^2.8.0" -vite-plugin-vue-devtools@^7.0.27: - version "7.0.27" - resolved "https://registry.yarnpkg.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.0.27.tgz#54a1bc09a02cc5e9785c9307cf54862ba7bf5dff" - integrity sha512-sb4B3ZGYueIiqQvQGCEDBsC8Byr4VnlUbbDS44DhYfcIEDChTSO0yRmJ3IJeESJQQMhEh3wS0cgQglL8A9lCuw== +vite-plugin-vue-devtools@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.1.3.tgz#e1105b5fd98f308b0a3c1fd1b68c0b2521752f14" + integrity sha512-qv8Z4yok9RYo6TEs89WnIAlmTHby/+XTim8tlSnMs3lAPcQqqcl/wGRY8gAeYrGCANngOqO+VuabW3Jb1HZtyw== dependencies: - "@vue/devtools-core" "^7.0.27" - "@vue/devtools-kit" "^7.0.27" - "@vue/devtools-shared" "^7.0.27" + "@vue/devtools-core" "^7.1.3" + "@vue/devtools-kit" "^7.1.3" + "@vue/devtools-shared" "^7.1.3" execa "^8.0.1" sirv "^2.0.4" - vite-plugin-inspect "^0.8.3" - vite-plugin-vue-inspector "^4.0.2" + vite-plugin-inspect "^0.8.4" + vite-plugin-vue-inspector "^5.0.1" -vite-plugin-vue-inspector@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-4.0.2.tgz#1d02646b20f4dc72cda0c2e0309551c7b332df73" - integrity sha512-KPvLEuafPG13T7JJuQbSm5PwSxKFnVS965+MP1we2xGw9BPkkc/+LPix5MMWenpKWqtjr0ws8THrR+KuoDC8hg== +vite-plugin-vue-inspector@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.0.1.tgz#e1d2a58b154bb7c6d3c414024f687a3a351125d6" + integrity sha512-R93P8iFa6BPODhc/aOtO04A8FFMMyFIfm8ZVSmN+8vU1TgwsHya734APGpX4fVHSPX2aVwYyiezXBUYQ0Opsqw== dependencies: "@babel/core" "^7.23.0" "@babel/plugin-proposal-decorators" "^7.23.0" @@ -3160,10 +3184,10 @@ vite-plugin-vue-inspector@^4.0.2: kolorist "^1.8.0" magic-string "^0.30.4" -vite@^5.2.9: - version "5.2.9" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.9.tgz#cd9a356c6ff5f7456c09c5ce74068ffa8df743d9" - integrity sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw== +vite@^5.2.10: + version "5.2.10" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.10.tgz#2ac927c91e99d51b376a5c73c0e4b059705f5bd7" + integrity sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw== dependencies: esbuild "^0.20.1" postcss "^8.4.38" @@ -3171,10 +3195,10 @@ vite@^5.2.9: optionalDependencies: fsevents "~2.3.3" -volar-service-prettier@^0.0.34: - version "0.0.34" - resolved "https://registry.yarnpkg.com/volar-service-prettier/-/volar-service-prettier-0.0.34.tgz#540e4fb16296aad70509ce39755bfa4cfd7b82d5" - integrity sha512-BNfJ8FwfPi1Wm/JkuzNjraOLdtKieGksNT/bDyquygVawv1QUzO2HB1hiMKfZGdcSFG5ZL9R0j7bBfRTfXA2gg== +volar-service-prettier@^0.0.42: + version "0.0.42" + resolved "https://registry.yarnpkg.com/volar-service-prettier/-/volar-service-prettier-0.0.42.tgz#90ce343f67e506ae5285db2d45fd30df2c382e72" + integrity sha512-TeO5piyqtjCPEu/7iAXnGl2OLP8SLyPUSPKAkqJ5NoQBWiflP3AdOCt+2C09MI/z+hv38Us9QIrFQO57e7852w== dependencies: vscode-uri "^3.0.8" @@ -3188,10 +3212,10 @@ vue-demi@>=0.14.5: resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.6.tgz#dc706582851dc1cdc17a0054f4fec2eb6df74c92" integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w== -vue-router@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.3.0.tgz#d5913f27bf68a0a178ee798c3c88be471811a235" - integrity sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ== +vue-router@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.3.2.tgz#08096c7765dacc6832f58e35f7a081a8b34116a7" + integrity sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q== dependencies: "@vue/devtools-api" "^6.5.1" @@ -3203,25 +3227,25 @@ vue-template-compiler@^2.7.14: de-indent "^1.0.2" he "^1.2.0" -vue-tsc@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.13.tgz#6ee557705456442e0f43ec0d1774ebf5ffec54f1" - integrity sha512-a3nL3FvguCWVJUQW/jFrUxdeUtiEkbZoQjidqvMeBK//tuE2w6NWQAbdrEpY2+6nSa4kZoKZp8TZUMtHpjt4mQ== +vue-tsc@^2.0.16: + version "2.0.16" + resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.16.tgz#ba82c4cdac283e8e39e30e817c8c1c967e528358" + integrity sha512-/gHAWJa216PeEhfxtAToIbxdWgw01wuQzo48ZUqMYVEyNqDp+OYV9xMO5HaPS2P3Ls0+EsjguMZLY4cGobX4Ew== dependencies: - "@volar/typescript" "2.2.0-alpha.8" - "@vue/language-core" "2.0.13" + "@volar/typescript" "~2.2.0" + "@vue/language-core" "2.0.16" semver "^7.5.4" -vue@^3.4.22: - version "3.4.22" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.22.tgz#3f498309ef464b44d00471dcae251d1382bf0c0b" - integrity sha512-CIx7NiP+n5WHBCG/fDNaUPP4qbQ5CIa8XIHZE3HpfS/rb2vmSIsp74BxsZyrrGKF0vHW3GoToqP3l0hzrMTecw== +vue@^3.4.26: + version "3.4.26" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.26.tgz#936c97e37672c737705d7bdfa62c31af18742269" + integrity sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg== dependencies: - "@vue/compiler-dom" "3.4.22" - "@vue/compiler-sfc" "3.4.22" - "@vue/runtime-dom" "3.4.22" - "@vue/server-renderer" "3.4.22" - "@vue/shared" "3.4.22" + "@vue/compiler-dom" "3.4.26" + "@vue/compiler-sfc" "3.4.26" + "@vue/runtime-dom" "3.4.26" + "@vue/server-renderer" "3.4.26" + "@vue/shared" "3.4.26" which@^2.0.1: version "2.0.2"