From 31f5ba1338c810d589b5b47be65ed245a8850e7f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 16 Mar 2025 19:16:43 +0100 Subject: [PATCH 01/31] add swagger --- Makefile | 10 ++++ backend/controller/bank_account/controller.go | 39 +++++++++++++++- bin/watch.sh | 19 ++++++++ cmd/server/server.go | 16 ++++++- go.mod | 32 +++++++++---- go.sum | 46 +++++++++++++++++++ 6 files changed, 152 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 552106d..9948b7d 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,16 @@ build: tpl front rice -tags=static_build \ -o $(EXECUTABLE_CMD) ./cmd/cli +.ONESHELL: +swagger: + directories="cmd/server,database/model" + + for i in backend/controller/*; do + directories="$$directories,$$i" + done + + swag init -d "cmd/server,$$directories" -g server.go + .PHONY: docker: docker build . -t gitnet.fr/deblan/budget-go diff --git a/backend/controller/bank_account/controller.go b/backend/controller/bank_account/controller.go index 90834c9..3090b51 100644 --- a/backend/controller/bank_account/controller.go +++ b/backend/controller/bank_account/controller.go @@ -38,6 +38,14 @@ func New(e *echo.Echo) *Controller { return &c } +// @Summary List bank accounts +// @Tags bank_account +// @Security ApiKeyAuth +// @Accept json +// @Produce json +// @Success 200 {object} crud.ListData +// @Success 403 +// @Router /api/bank_account [get] func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) @@ -46,6 +54,16 @@ func (ctrl *Controller) List(c echo.Context) error { return ctrl.crud.With(ctrl.Config()).List(c) } +// @Summary Show a bank account +// @Tags bank_account +// @Security ApiKeyAuth +// @Accept json +// @Produce json +// @Success 200 {object} model.BankAccount +// @Success 403 +// @Success 404 +// @Param id path int true "ID" +// @Router /api/bank_account/{id} [get] func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) @@ -54,6 +72,16 @@ func (ctrl *Controller) Show(c echo.Context) error { return ctrl.crud.With(ctrl.Config()).Show(c) } +// @Summary Delete a bank account +// @Tags bank_account +// @Security ApiKeyAuth +// @Accept json +// @Produce json +// @Success 200 +// @Success 403 +// @Success 400 +// @Param id path int true "ID" +// @Router /api/bank_account/{id} [delete] func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) @@ -62,6 +90,16 @@ func (ctrl *Controller) Delete(c echo.Context) error { return ctrl.crud.With(ctrl.Config()).Delete(c) } +// @Summary Create a bank account +// @Tags bank_account +// @Security ApiKeyAuth +// @Accept json +// @Produce json +// @Success 200 {object} model.BankAccount +// @Success 403 +// @Success 400 +// @Param label body string true "Name" +// @Router /api/bank_account [post] func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) @@ -79,7 +117,6 @@ func (ctrl *Controller) Create(c echo.Context) error { return item, nil }) - } func (ctrl *Controller) Update(c echo.Context) error { diff --git a/bin/watch.sh b/bin/watch.sh index b9a58f2..8342fb6 100755 --- a/bin/watch.sh +++ b/bin/watch.sh @@ -2,12 +2,31 @@ export TEMPL_EXPERIMENT=rawgo +title() { + printf -- "# %s\n" "$1" +} + while true; do + clear + + title "Remove rice-box" rm -f cmd/server/rice-box.go + + title "Build assets" ./node_modules/.bin/webpack + + title "Make templates" make tpl + + title "Make swagger" + make swagger + + title "Start server" screen -S budget -d -m go run ./cmd/server + + title "Notify" notify-send "Budget" "Ready!" + inotifywait -r . -e close_write screen -X -S budget quit done diff --git a/cmd/server/server.go b/cmd/server/server.go index d8a6ead..360fbfc 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -14,10 +14,14 @@ import ( "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" + echoSwagger "github.com/swaggo/echo-swagger" + + // _ "github.com/swaggo/echo-swagger/example/docs" + "gitnet.fr/deblan/budget/backend/router" "gitnet.fr/deblan/budget/config" "gitnet.fr/deblan/budget/database/manager" "gitnet.fr/deblan/budget/database/model" - "gitnet.fr/deblan/budget/backend/router" + "gitnet.fr/deblan/budget/docs" ) type TemplateRenderer struct { @@ -32,7 +36,16 @@ func (cv *AppValidator) Validate(i interface{}) error { return cv.validator.Struct(i) } +// @securityDefinitions.apikey ApiKeyAuth +// @in header +// @name x-api-key func main() { + docs.SwaggerInfo.Title = "Budget API" + docs.SwaggerInfo.Description = "API" + docs.SwaggerInfo.Version = "1.0" + docs.SwaggerInfo.BasePath = "/" + docs.SwaggerInfo.Schemes = []string{"http", "https"} + ini := flag.String("c", "config.ini", "Path to config.ini") conf := config.Get() conf.Load(*ini) @@ -50,6 +63,7 @@ func main() { assetHandler := http.FileServer(rice.MustFindBox("../../backend/view/static").HTTPBox()) e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler))) + e.GET("/swagger/*", echoSwagger.WrapHandler) e.Use(middleware.Logger()) router.RegisterControllers(e) diff --git a/go.mod b/go.mod index e24a22a..05d7225 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/manifoldco/promptui v0.9.0 github.com/urfave/cli/v2 v2.27.4 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.35.0 gopkg.in/ini.v1 v1.67.0 gorm.io/driver/mysql v1.5.7 gorm.io/gorm v1.25.12 @@ -14,11 +14,19 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/GeertJohan/go.rice v1.0.3 // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.2.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/a-h/templ v0.2.778 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/daaku/go.zipexe v1.0.2 // indirect github.com/gabriel-vasile/mimetype v1.4.5 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator v9.31.0+incompatible // indirect @@ -30,19 +38,27 @@ require ( github.com/gorilla/sessions v1.4.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/labstack/echo-contrib v0.17.1 // indirect - github.com/labstack/echo/v4 v4.12.0 // indirect + github.com/labstack/echo/v4 v4.13.3 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect + github.com/stretchr/testify v1.10.0 // indirect + github.com/swaggo/echo-swagger v1.4.1 // indirect + github.com/swaggo/files/v2 v2.0.2 // indirect + github.com/swaggo/swag v1.16.4 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index bab4ae2..e2290bd 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,12 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4 github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI= github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28= +github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM= github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= @@ -23,6 +29,16 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -47,18 +63,27 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labstack/echo-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU= github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= +github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= +github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -76,6 +101,13 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk= +github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc= +github.com/swaggo/files/v2 v2.0.2 h1:Bq4tgS/yxLB/3nwOMcul5oLEUKa877Ykgz3CJMVbQKU= +github.com/swaggo/files/v2 v2.0.2/go.mod h1:TVqetIzZsO9OhHX1Am9sRf9LdrFZqoK49N37KON/jr0= +github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A= +github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg= github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -87,22 +119,36 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +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= From ec45abd9112345145e076dbbd5e53b5444e7a140 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 16 Mar 2025 22:36:38 +0100 Subject: [PATCH 02/31] feat(security): set secure auth cookie --- backend/controller/auth/controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/controller/auth/controller.go b/backend/controller/auth/controller.go index e87f52d..96c2ed2 100644 --- a/backend/controller/auth/controller.go +++ b/backend/controller/auth/controller.go @@ -50,6 +50,7 @@ func (ctrl *Controller) LoginPost(c echo.Context) error { Path: "/", MaxAge: 3600 * 24 * 2, HttpOnly: true, + Secure: true, } sess.Values["user"] = user.ID sess.Save(c.Request(), c.Response()) From e535deb8b5447ce0f723885526338ef923771323 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 16 Mar 2025 23:06:03 +0100 Subject: [PATCH 03/31] fix some of sonarqube review --- Dockerfile | 2 +- backend/controller/auth/controller.go | 9 ++++--- backend/controller/bank_account/controller.go | 24 +++++++++++-------- backend/controller/category/controller.go | 24 +++++++++++-------- backend/controller/collabora/controller.go | 7 +++--- backend/controller/crud/crud.go | 7 +++--- backend/controller/file/controller.go | 15 ++++++------ .../controller/saving_account/controller.go | 24 +++++++++++-------- backend/controller/transaction/controller.go | 9 +++---- backend/controller/user/controller.go | 24 +++++++++++-------- backend/message/message.go | 8 +++++++ frontend/js/App.vue | 2 -- 12 files changed, 92 insertions(+), 63 deletions(-) create mode 100644 backend/message/message.go diff --git a/Dockerfile b/Dockerfile index 5ee2340..9a33285 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine +FROM alpine:3 COPY ./budget-go /usr/bin/ COPY ./budget-go-client /usr/bin/ diff --git a/backend/controller/auth/controller.go b/backend/controller/auth/controller.go index 96c2ed2..b3650f9 100644 --- a/backend/controller/auth/controller.go +++ b/backend/controller/auth/controller.go @@ -18,9 +18,12 @@ type Controller struct { func New(e *echo.Echo) *Controller { c := Controller{} - e.GET("/login", c.LoginGet) - e.POST("/login", c.LoginPost) - e.GET("/logout", c.LogoutGet) + loginRoute := "/login" + logoutRoute := "/logout" + + e.GET(loginRoute, c.LoginGet) + e.POST(loginRoute, c.LoginPost) + e.GET(logoutRoute, c.LogoutGet) return &c } diff --git a/backend/controller/bank_account/controller.go b/backend/controller/bank_account/controller.go index 90834c9..bdf0073 100644 --- a/backend/controller/bank_account/controller.go +++ b/backend/controller/bank_account/controller.go @@ -3,6 +3,7 @@ package bank_account import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/model" "gorm.io/gorm" ) @@ -29,18 +30,21 @@ func New(e *echo.Echo) *Controller { crud: crud.New(), } - e.GET("/api/bank_account", c.List) - e.POST("/api/bank_account", c.Create) - e.GET("/api/bank_account/:id", c.Show) - e.POST("/api/bank_account/:id", c.Update) - e.DELETE("/api/bank_account/:id", c.Delete) + listRoute := "/api/bank_account" + itemRoute := "/api/bank_account/:id" + + e.GET(listRoute, c.List) + e.POST(listRoute, c.Create) + e.GET(itemRoute, c.Show) + e.POST(itemRoute, c.Update) + e.DELETE(itemRoute, c.Delete) return &c } func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).List(c) @@ -48,7 +52,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Show(c) @@ -56,7 +60,7 @@ func (ctrl *Controller) Show(c echo.Context) error { func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Delete(c) @@ -64,7 +68,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { @@ -84,7 +88,7 @@ func (ctrl *Controller) Create(c echo.Context) error { func (ctrl *Controller) Update(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { diff --git a/backend/controller/category/controller.go b/backend/controller/category/controller.go index adf0d5d..921585b 100644 --- a/backend/controller/category/controller.go +++ b/backend/controller/category/controller.go @@ -3,6 +3,7 @@ package category import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/manager" "gitnet.fr/deblan/budget/database/model" "gorm.io/gorm" @@ -36,18 +37,21 @@ func New(e *echo.Echo) *Controller { crud: crud.New(), } - e.GET("/api/category", c.List) - e.POST("/api/category", c.Create) - e.GET("/api/category/:id", c.Show) - e.POST("/api/category/:id", c.Update) - e.DELETE("/api/category/:id", c.Delete) + listRoute := "/api/category" + itemRoute := "/api/category/:id" + + e.GET(listRoute, c.List) + e.POST(listRoute, c.Create) + e.GET(itemRoute, c.Show) + e.POST(itemRoute, c.Update) + e.DELETE(itemRoute, c.Delete) return &c } func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).List(c) @@ -55,7 +59,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Show(c) @@ -63,7 +67,7 @@ func (ctrl *Controller) Show(c echo.Context) error { func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Delete(c) @@ -71,7 +75,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { @@ -94,7 +98,7 @@ func (ctrl *Controller) Create(c echo.Context) error { func (ctrl *Controller) Update(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { diff --git a/backend/controller/collabora/controller.go b/backend/controller/collabora/controller.go index 491e1b0..d7c50de 100644 --- a/backend/controller/collabora/controller.go +++ b/backend/controller/collabora/controller.go @@ -12,6 +12,7 @@ import ( "time" "github.com/labstack/echo/v4" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/backend/view" tpl "gitnet.fr/deblan/budget/backend/view/template/collabora" "gitnet.fr/deblan/budget/config" @@ -105,7 +106,7 @@ func (ctrl *Controller) Info(c echo.Context) error { } if file == "" { - return c.JSON(404, "File not found") + return c.JSON(404, message.FileNotFound) } fi, _ := os.Stat(file) @@ -141,7 +142,7 @@ func (ctrl *Controller) WopiContentGet(c echo.Context) error { } if file == "" { - return c.JSON(404, "File not found") + return c.JSON(404, message.FileNotFound) } content, _ := os.ReadFile(file) @@ -165,7 +166,7 @@ func (ctrl *Controller) WopiContentPost(c echo.Context) error { } if file == "" { - return c.JSON(404, "File not found") + return c.JSON(404, message.FileNotFound) } data, _ := ioutil.ReadAll(c.Request().Body) diff --git a/backend/controller/crud/crud.go b/backend/controller/crud/crud.go index ebe409b..1ce1fb6 100644 --- a/backend/controller/crud/crud.go +++ b/backend/controller/crud/crud.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/labstack/echo/v4" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/manager" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -130,7 +131,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { if count == 0 { return c.JSON(404, Error{ Code: 404, - Message: "Not found", + Message: message.NotFound, }) } @@ -146,7 +147,7 @@ func (ctrl *Controller) Create(c echo.Context, body interface{}, createCallback if err := c.Bind(body); err != nil { return c.JSON(400, Error{ Code: 400, - Message: "Bad request", + Message: message.BadRequest, }) } @@ -186,7 +187,7 @@ func (ctrl *Controller) Update(c echo.Context, body interface{}, updateCallback if count == 0 { return c.JSON(404, Error{ Code: 404, - Message: "Not found", + Message: message.NotFound, }) } diff --git a/backend/controller/file/controller.go b/backend/controller/file/controller.go index 31efba5..9c1cc5a 100644 --- a/backend/controller/file/controller.go +++ b/backend/controller/file/controller.go @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/config" "gitnet.fr/deblan/budget/database/model" f "gitnet.fr/deblan/budget/file" @@ -31,7 +32,7 @@ func New(e *echo.Echo) *Controller { func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } tree := f.GetTree("", config.Get().File.Path) @@ -41,7 +42,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) CreateFile(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } file, err := c.FormFile("file") @@ -77,7 +78,7 @@ func (ctrl *Controller) CreateFile(c echo.Context) error { func (ctrl *Controller) CreateDirectory(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { @@ -126,7 +127,7 @@ func (ctrl *Controller) CreateDirectory(c echo.Context) error { func (ctrl *Controller) Download(c echo.Context) error { if nil == model.LoadUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } var file string @@ -143,7 +144,7 @@ func (ctrl *Controller) Download(c echo.Context) error { } if file == "" { - return c.JSON(404, "File not found") + return c.JSON(404, message.FileNotFound) } content, _ := os.ReadFile(file) @@ -153,7 +154,7 @@ func (ctrl *Controller) Download(c echo.Context) error { func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } var file string @@ -177,7 +178,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { } if file == "" { - return c.JSON(404, "File not found") + return c.JSON(404, message.FileNotFound) } os.RemoveAll(file) diff --git a/backend/controller/saving_account/controller.go b/backend/controller/saving_account/controller.go index 03ac10e..64f7325 100644 --- a/backend/controller/saving_account/controller.go +++ b/backend/controller/saving_account/controller.go @@ -3,6 +3,7 @@ package saving_account import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/model" "gorm.io/gorm" ) @@ -29,18 +30,21 @@ func New(e *echo.Echo) *Controller { crud: crud.New(), } - e.GET("/api/saving_account", c.List) - e.POST("/api/saving_account", c.Create) - e.GET("/api/saving_account/:id", c.Show) - e.POST("/api/saving_account/:id", c.Update) - e.DELETE("/api/saving_account/:id", c.Delete) + listRoute := "/api/saving_account" + itemRoute := "/api/saving_account/:id" + + e.GET(listRoute, c.List) + e.POST(listRoute, c.Create) + e.GET(itemRoute, c.Show) + e.POST(itemRoute, c.Update) + e.DELETE(itemRoute, c.Delete) return &c } func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).List(c) @@ -48,7 +52,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Show(c) @@ -56,7 +60,7 @@ func (ctrl *Controller) Show(c echo.Context) error { func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Delete(c) @@ -64,7 +68,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { @@ -86,7 +90,7 @@ func (ctrl *Controller) Create(c echo.Context) error { func (ctrl *Controller) Update(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { diff --git a/backend/controller/transaction/controller.go b/backend/controller/transaction/controller.go index 1c94964..4bea315 100644 --- a/backend/controller/transaction/controller.go +++ b/backend/controller/transaction/controller.go @@ -7,6 +7,7 @@ import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/manager" "gitnet.fr/deblan/budget/database/model" "gorm.io/gorm" @@ -50,7 +51,7 @@ func New(e *echo.Echo) *Controller { func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).List(c) @@ -58,7 +59,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Show(c) @@ -66,7 +67,7 @@ func (ctrl *Controller) Show(c echo.Context) error { func (ctrl *Controller) UpdateCategories(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } datas := model.UpdateTransactionsCategories() @@ -76,7 +77,7 @@ func (ctrl *Controller) UpdateCategories(c echo.Context) error { func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } db := manager.Get().Db diff --git a/backend/controller/user/controller.go b/backend/controller/user/controller.go index b8d4ff7..9957240 100644 --- a/backend/controller/user/controller.go +++ b/backend/controller/user/controller.go @@ -3,6 +3,7 @@ package user import ( "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" + "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/database/model" "gorm.io/gorm" ) @@ -28,18 +29,21 @@ func New(e *echo.Echo) *Controller { crud: crud.New(), } - e.GET("/api/user", c.List) - e.POST("/api/user", c.Create) - e.GET("/api/user/:id", c.Show) - e.POST("/api/user/:id", c.Update) - e.DELETE("/api/user/:id", c.Delete) + listRoute := "/api/user" + itemRoute := "/api/user/:id" + + e.GET(listRoute, c.List) + e.POST(listRoute, c.Create) + e.GET(itemRoute, c.Show) + e.POST(itemRoute, c.Update) + e.DELETE(itemRoute, c.Delete) return &c } func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).List(c) @@ -47,7 +51,7 @@ func (ctrl *Controller) List(c echo.Context) error { func (ctrl *Controller) Show(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Show(c) @@ -55,7 +59,7 @@ func (ctrl *Controller) Show(c echo.Context) error { func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } return ctrl.crud.With(ctrl.Config()).Delete(c) @@ -63,7 +67,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { func (ctrl *Controller) Create(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { @@ -84,7 +88,7 @@ func (ctrl *Controller) Create(c echo.Context) error { func (ctrl *Controller) Update(c echo.Context) error { if nil == model.LoadApiUser(c) { - return c.JSON(403, crud.Error{Code: 403, Message: "Login required"}) + return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { diff --git a/backend/message/message.go b/backend/message/message.go new file mode 100644 index 0000000..be386e1 --- /dev/null +++ b/backend/message/message.go @@ -0,0 +1,8 @@ +package message + +var ( + LoginRequired = "Login required" + FileNotFound = "File not found" + NotFound = "Not found" + BadRequest = "Bad request" +) diff --git a/frontend/js/App.vue b/frontend/js/App.vue index 55f13e7..3de8f32 100644 --- a/frontend/js/App.vue +++ b/frontend/js/App.vue @@ -57,5 +57,3 @@ import {BNavItem} from 'bootstrap-vue-next' - - From b5cd785b4ed732eaf22d9fc1dd4a55704b49b370 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 16 Mar 2025 23:22:33 +0100 Subject: [PATCH 04/31] fix sonarqube review --- backend/controller/crud/crud.go | 14 +++++++++----- database/model/transaction.go | 10 ---------- frontend/js/chart/capital.js | 2 +- frontend/js/chart/debitAverage.js | 4 ++-- frontend/js/chart/diffCreditDebit.js | 2 +- frontend/js/chart/distribution.js | 6 +++--- frontend/js/chart/monthThreshold.js | 6 +++--- frontend/js/components/Filters.vue | 2 +- frontend/js/views/DashboardView.vue | 2 +- frontend/js/views/FilesView.vue | 1 + frontend/js/views/UsersView.vue | 2 +- 11 files changed, 23 insertions(+), 28 deletions(-) diff --git a/backend/controller/crud/crud.go b/backend/controller/crud/crud.go index 1ce1fb6..c85a9a5 100644 --- a/backend/controller/crud/crud.go +++ b/backend/controller/crud/crud.go @@ -36,6 +36,10 @@ func (ctrl *Controller) With(config Configuration) *Controller { return ctrl } +var ( + IdEqual = "id = ?" +) + func (ctrl *Controller) List(c echo.Context) error { db := manager.Get().Db db = db.Model(ctrl.Config.Model) @@ -93,7 +97,7 @@ func (ctrl *Controller) Show(c echo.Context) error { } var count int64 - db.Model(ctrl.Config.Model).Where("id = ?", value).Count(&count) + db.Model(ctrl.Config.Model).Where(IdEqual, value).Count(&count) if count == 0 { return c.JSON(404, Error{ @@ -103,7 +107,7 @@ func (ctrl *Controller) Show(c echo.Context) error { } item := ctrl.Config.CreateModel() - db.Model(ctrl.Config.Model).Where("id = ?", value) + db.Model(ctrl.Config.Model).Where(IdEqual, value) if ctrl.Config.ItemQuery != nil { ctrl.Config.ItemQuery(db) @@ -126,7 +130,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { } var count int64 - db.Model(ctrl.Config.Model).Where("id = ?", value).Count(&count) + db.Model(ctrl.Config.Model).Where(IdEqual, value).Count(&count) if count == 0 { return c.JSON(404, Error{ @@ -136,7 +140,7 @@ func (ctrl *Controller) Delete(c echo.Context) error { } item := ctrl.Config.CreateModel() - db.Model(ctrl.Config.Model).Where("id = ?", value).Delete(&item) + db.Model(ctrl.Config.Model).Where(IdEqual, value).Delete(&item) return c.JSON(200, nil) } @@ -182,7 +186,7 @@ func (ctrl *Controller) Update(c echo.Context, body interface{}, updateCallback } var count int64 - db.Model(ctrl.Config.Model).Where("id = ?", value).Count(&count) + db.Model(ctrl.Config.Model).Where(IdEqual, value).Count(&count) if count == 0 { return c.JSON(404, Error{ diff --git a/database/model/transaction.go b/database/model/transaction.go index 641f841..2ab9a57 100644 --- a/database/model/transaction.go +++ b/database/model/transaction.go @@ -64,8 +64,6 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { if match { counter += 8 } - } else { - match = match && true } if rule.BankCategory != nil { @@ -75,8 +73,6 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { if match { counter += 6 } - } else { - match = match && true } if rule.Amount != nil { @@ -85,8 +81,6 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { if match { counter += 4 } - } else { - match = match && true } if rule.DateFrom != nil { @@ -95,8 +89,6 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { if match { counter += 2 } - } else { - match = match && true } if rule.DateTo != nil { @@ -105,8 +97,6 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { if match { counter += 2 } - } else { - match = match && true } return match, counter diff --git a/frontend/js/chart/capital.js b/frontend/js/chart/capital.js index 567f6fd..91e8cb5 100644 --- a/frontend/js/chart/capital.js +++ b/frontend/js/chart/capital.js @@ -50,7 +50,7 @@ const compute = (transactions, precision, dateFrom, dateTo) => { transactions.forEach((transaction) => { let date = getDate(transaction.date, precision) - let begin = !Object.prototype.hasOwnProperty.call(indexes, date) + let begin = !Object.hasOwn(indexes, date) if (begin) { indexes[date] = labels.length diff --git a/frontend/js/chart/debitAverage.js b/frontend/js/chart/debitAverage.js index f1a2848..e9cc245 100644 --- a/frontend/js/chart/debitAverage.js +++ b/frontend/js/chart/debitAverage.js @@ -36,7 +36,7 @@ const compute = (transactions, dateFrom, dateTo, order) => { let category = transaction.category ?? emptyCategory - if (!Object.prototype.hasOwnProperty.call(data, category.label)) { + if (!Object.hasOwn(data, category.label)) { data[category.label] = { category: category, average: 0, @@ -52,7 +52,7 @@ const compute = (transactions, dateFrom, dateTo, order) => { const date = getDate(transaction.date) - if (!Object.prototype.hasOwnProperty.call(data[category.label].months, date)) { + if (!Object.hasOwn(data[category.label].months, date)) { data[category.label].months[date] = 0 } diff --git a/frontend/js/chart/diffCreditDebit.js b/frontend/js/chart/diffCreditDebit.js index 16e2745..6cd8fb8 100644 --- a/frontend/js/chart/diffCreditDebit.js +++ b/frontend/js/chart/diffCreditDebit.js @@ -39,7 +39,7 @@ const compute = (transactions, dateFrom, dateTo) => { const date = getDate(transaction.date) - if (!Object.prototype.hasOwnProperty.call(indexes, date)) { + if (!Object.hasOwn(indexes, date)) { indexes[date] = labels.length values[date] = 0 labels.push(date) diff --git a/frontend/js/chart/distribution.js b/frontend/js/chart/distribution.js index 8724527..c4b88d7 100644 --- a/frontend/js/chart/distribution.js +++ b/frontend/js/chart/distribution.js @@ -42,12 +42,12 @@ const computeBar = ( let date = getDate(transaction.date) - if (!Object.prototype.hasOwnProperty.call(indexes, date)) { + if (!Object.hasOwn(indexes, date)) { indexes[date] = labels.length labels.push(date) } - if (!Object.prototype.hasOwnProperty.call(bars, category.label)) { + if (!Object.hasOwn(bars, category.label)) { bars[category.label] = { label: category.label, data: [], @@ -137,7 +137,7 @@ const computeDoughnut = ( return } - if (!Object.prototype.hasOwnProperty.call(indexes, category.id)) { + if (!Object.hasOwn(indexes, category.id)) { indexes[category.id] = labels.length labels.push(category.label) backgroundColor.push(category.color) diff --git a/frontend/js/chart/monthThreshold.js b/frontend/js/chart/monthThreshold.js index 6f01e4b..08ef841 100644 --- a/frontend/js/chart/monthThreshold.js +++ b/frontend/js/chart/monthThreshold.js @@ -26,7 +26,7 @@ const compute = (transactions, cats, dateFrom, dateTo) => { transactions.forEach((value) => { if ( value.category === null || - !Object.prototype.hasOwnProperty.call(categories, value.category.id) + !Object.hasOwn(categories, value.category.id) ) { return } @@ -37,12 +37,12 @@ const compute = (transactions, cats, dateFrom, dateTo) => { const date = getDate(value.date) - if (!Object.prototype.hasOwnProperty.call(datas, date)) { + if (!Object.hasOwn(datas, date)) { datas[date] = {} } if ( - !Object.prototype.hasOwnProperty.call( + !Object.hasOwn( datas[date], value.category.id.toString(), ) diff --git a/frontend/js/components/Filters.vue b/frontend/js/components/Filters.vue index d32f5a8..53bb7c3 100644 --- a/frontend/js/components/Filters.vue +++ b/frontend/js/components/Filters.vue @@ -154,7 +154,7 @@ const doAdd = () => { } const doRemove = (key) => { - var items = [] + let items = [] dataValue.value.forEach((v, k) => { if (k !== key) { diff --git a/frontend/js/views/DashboardView.vue b/frontend/js/views/DashboardView.vue index 344968f..d284179 100644 --- a/frontend/js/views/DashboardView.vue +++ b/frontend/js/views/DashboardView.vue @@ -106,7 +106,7 @@ From a6f3ed315b36adc81b3732c3ec93c2aa968788b0 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 23 Mar 2025 17:44:30 +0100 Subject: [PATCH 05/31] update ui --- backend/view/template/auth/login.templ | 4 +- backend/view/template/auth/login_templ.go | 2 +- frontend/js/App.vue | 9 ++- frontend/js/components/crud/Header.vue | 11 +++- frontend/js/components/crud/Pager.vue | 2 +- frontend/js/views/BankAccountsView.vue | 16 +++--- frontend/js/views/CategoriesView.vue | 16 +++--- frontend/js/views/DashboardView.vue | 7 ++- frontend/js/views/SavingAccountsView.vue | 16 +++--- frontend/js/views/TransactionsView.vue | 15 ++--- frontend/js/views/UsersView.vue | 16 +++--- frontend/scss/main.scss | 70 +++++++++++++++-------- 12 files changed, 108 insertions(+), 76 deletions(-) diff --git a/backend/view/template/auth/login.templ b/backend/view/template/auth/login.templ index c429698..cedee05 100644 --- a/backend/view/template/auth/login.templ +++ b/backend/view/template/auth/login.templ @@ -11,9 +11,9 @@ templ Page(hasError bool) {
-
+
-
+
diff --git a/backend/view/template/auth/login_templ.go b/backend/view/template/auth/login_templ.go index 8e57ce8..26b4600 100644 --- a/backend/view/template/auth/login_templ.go +++ b/backend/view/template/auth/login_templ.go @@ -39,7 +39,7 @@ func Page(hasError bool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Budget
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Budget
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/frontend/js/App.vue b/frontend/js/App.vue index 3de8f32..3b9c9e1 100644 --- a/frontend/js/App.vue +++ b/frontend/js/App.vue @@ -11,7 +11,7 @@ import {BNavItem} from 'bootstrap-vue-next' > @@ -27,7 +27,7 @@ import {BNavItem} from 'bootstrap-vue-next' '/bank_accounts', '/saving_accounts', '/files', - 'users', + '/users', ]" v-slot="{href, route, navigate, isActive, isExactActive}" :to="url" @@ -36,7 +36,6 @@ import {BNavItem} from 'bootstrap-vue-next' - - Déconnexion + + Déconnexion
diff --git a/frontend/js/components/crud/Header.vue b/frontend/js/components/crud/Header.vue index 80ccaa3..74daf36 100644 --- a/frontend/js/components/crud/Header.vue +++ b/frontend/js/components/crud/Header.vue @@ -1,7 +1,12 @@ diff --git a/frontend/js/components/crud/Pager.vue b/frontend/js/components/crud/Pager.vue index ac91cb3..5301c3e 100644 --- a/frontend/js/components/crud/Pager.vue +++ b/frontend/js/components/crud/Pager.vue @@ -1,5 +1,5 @@ + - -
diff --git a/frontend/js/views/CategoriesView.vue b/frontend/js/views/CategoriesView.vue index 39cda66..8de39d8 100644 --- a/frontend/js/views/CategoriesView.vue +++ b/frontend/js/views/CategoriesView.vue @@ -25,20 +25,20 @@ > + - -
diff --git a/frontend/js/views/DashboardView.vue b/frontend/js/views/DashboardView.vue index d284179..400d830 100644 --- a/frontend/js/views/DashboardView.vue +++ b/frontend/js/views/DashboardView.vue @@ -101,7 +101,10 @@
-
Chargement...
+
+

Chargement...

+ +
@@ -109,7 +112,7 @@ import {ref, onMounted, watch} from 'vue' import {compute as monthThresholds} from '../chart/monthThreshold' import {getStorage, saveStorage} from '../lib/storage' -import {BButtonGroup, BButton} from 'bootstrap-vue-next' +import {BButtonGroup, BButton, BSpinner} from 'bootstrap-vue-next' import Filters from './../components/dashboard/Filters.vue' import Capital from './../components/dashboard/Capital.vue' import SavingAccounts from './../components/dashboard/SavingAccounts.vue' diff --git a/frontend/js/views/SavingAccountsView.vue b/frontend/js/views/SavingAccountsView.vue index a8da9b4..68d8770 100644 --- a/frontend/js/views/SavingAccountsView.vue +++ b/frontend/js/views/SavingAccountsView.vue @@ -13,20 +13,20 @@ > + - -
diff --git a/frontend/js/views/TransactionsView.vue b/frontend/js/views/TransactionsView.vue index c26ae9f..43cea1f 100644 --- a/frontend/js/views/TransactionsView.vue +++ b/frontend/js/views/TransactionsView.vue @@ -19,15 +19,16 @@ > + - - + - -
diff --git a/frontend/scss/main.scss b/frontend/scss/main.scss index d39cd61..374749e 100644 --- a/frontend/scss/main.scss +++ b/frontend/scss/main.scss @@ -1,10 +1,16 @@ $white: #ffffff; $theme-colors: ( - 'light': #bfecf8, + 'navBg': #f5f6f7, + 'navText': #47516B, + 'navActiveBg': #3072c7, + 'headerText': #47516B, + 'headerBg': #fff, + 'light': #f1c3a2, 'dark': #07070b, - 'primary': #293e5b, - 'secondary': #4e76ac, + 'primary': #3072c7, + 'secondary': #a2c7e7, + 'header': #d6c52e, 'info': #abca41, 'success': #1eaa62, 'warning': #e5cc1d, @@ -12,13 +18,13 @@ $theme-colors: ( ); $pagination-active-bg: map-get($theme-colors, 'secondary'); -$nav-pills-link-active-bg: darken(map-get($theme-colors, 'primary'), 5%); +$nav-pills-link-active-bg: map-get($theme-colors, 'navActiveBg'); @import '~bootstrap/scss/bootstrap'; @import '~bootstrap-vue-next/dist/bootstrap-vue-next.css'; @import '~@fortawesome/fontawesome-free/css/all.css'; -$light-grey: #e9ecef; +$light-grey: #f5f6f7; #app-name { padding-left: 8px; @@ -27,21 +33,19 @@ $light-grey: #e9ecef; #login-form { background: linear-gradient( -45deg, - map-get($theme-colors, 'primary') 50%, - map-get($theme-colors, 'secondary') 100% + #f1f1f1 50%, + #e1e1e1 100% ); .card { background: linear-gradient( -45deg, - darken(map-get($theme-colors, 'primary'), 10%) 50%, - map-get($theme-colors, 'secondary') 100% + #f1f1f1 50%, + #e1e1e1 100% ); } -} -* { - overscroll-behavior: contain !important; + color: #47516B; } .cursor { @@ -60,7 +64,11 @@ $nav-size-sm: 50px; #nav { width: $nav-size; - background: map-get($theme-colors, 'primary'); + background: map-get($theme-colors, 'navBg'); + + a:not(.active) { + color: map-get($theme-colors, 'navText'); + } i { width: 20px; @@ -77,7 +85,7 @@ $nav-size-sm: 50px; box-shadow 0.2s; &:hover { - box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 6px rgba(0, 0, 0, 0.2); } canvas { @@ -92,17 +100,28 @@ $nav-size-sm: 50px; .crud { &-list { - width: calc(100vw - $nav-size - 30px); - padding: 20px; - background: $light-grey; - border-radius: 10px; - - margin-left: 15px; - margin-right: 15px; + width: 100%; th, td { - background: $light-grey; + vertical-align: middle; + padding-top: 1rem; + padding-bottom: 1rem; + transition: background 0.5s; + } + + tr { + td:first-child, th:first-child { + padding-left: 1rem; + } + + td:last-child, th:last-child { + padding-right: 1rem; + } + + &:hover td { + background: $light-grey; + } } thead th { @@ -171,7 +190,7 @@ $nav-size-sm: 50px; .crud { &-list { - width: calc(100vw - $nav-size-sm - 30px); + width: calc(100vw - $nav-size-sm); overflow: scroll; } } @@ -180,3 +199,8 @@ $nav-size-sm: 50px; width: calc(100vw - $nav-size-sm); } } + +.header { + background: map-get($theme-colors, 'headerBg'); + color: map-get($theme-colors, 'headerText'); +} From 262b9cab1799618f129fb8b4ed2e181476fef6d7 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 23 Mar 2025 18:18:00 +0100 Subject: [PATCH 06/31] change default font to ubuntu --- frontend/scss/main.scss | 12 ++++++++---- package-lock.json | 10 ++++++++++ package.json | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/scss/main.scss b/frontend/scss/main.scss index 374749e..71afbe8 100644 --- a/frontend/scss/main.scss +++ b/frontend/scss/main.scss @@ -4,8 +4,6 @@ $theme-colors: ( 'navBg': #f5f6f7, 'navText': #47516B, 'navActiveBg': #3072c7, - 'headerText': #47516B, - 'headerBg': #fff, 'light': #f1c3a2, 'dark': #07070b, 'primary': #3072c7, @@ -23,6 +21,11 @@ $nav-pills-link-active-bg: map-get($theme-colors, 'navActiveBg'); @import '~bootstrap/scss/bootstrap'; @import '~bootstrap-vue-next/dist/bootstrap-vue-next.css'; @import '~@fortawesome/fontawesome-free/css/all.css'; +@import "@fontsource/ubuntu/300.css"; + +body { + font-family: "Ubuntu"; +} $light-grey: #f5f6f7; @@ -201,6 +204,7 @@ $nav-size-sm: 50px; } .header { - background: map-get($theme-colors, 'headerBg'); - color: map-get($theme-colors, 'headerText'); + background-image: linear-gradient(45deg, #fafafa 25%, #f5f6f7 25%, #f5f6f7 50%, #fafafa 50%, #fafafa 75%, #f5f6f7 75%, #f5f6f7 100%); + background-size: 56.57px 56.57px; + color: #47516B; } diff --git a/package-lock.json b/package-lock.json index 3ca345c..cbc00f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "@fontsource/ubuntu": "^5.2.5", "@fortawesome/fontawesome-free": "^6.6.0", "@symfony/webpack-encore": "github:symfony/webpack-encore", "bootstrap": "^5.3.3", @@ -2423,6 +2424,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fontsource/ubuntu": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/ubuntu/-/ubuntu-5.2.5.tgz", + "integrity": "sha512-VKVFVqmJ9MGnOJW2dsQ982qHN8Zr+tNeEwEHnzt5VdGi9ZWL37wYFD32YsqukWlI/+I7v5ZkgHTEAvsZxU6aDA==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/@fortawesome/fontawesome-free": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", diff --git a/package.json b/package.json index b21fd01..d2cbc14 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "@fontsource/ubuntu": "^5.2.5", "@fortawesome/fontawesome-free": "^6.6.0", "@symfony/webpack-encore": "github:symfony/webpack-encore", "bootstrap": "^5.3.3", From 58b78dd3359a88867af9a809e64985e49fb361fc Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 25 Mar 2025 22:54:34 +0100 Subject: [PATCH 07/31] refactoring: add sub routes and slit in several components --- database/model/transaction.go | 5 + frontend/js/App.vue | 2 +- frontend/js/components/crud/DataList.vue | 94 +++ frontend/js/components/crud/FormView.vue | 28 + frontend/js/components/crud/FormWidget.vue | 164 +++++ frontend/js/components/crud/Header.vue | 12 +- frontend/js/router/index.js | 110 ++- frontend/js/views/BankAccountsView.vue | 319 --------- frontend/js/views/CategoriesView.vue | 648 ------------------ frontend/js/views/ComponentView.vue | 3 + frontend/js/views/SavingAccountsView.vue | 369 ---------- frontend/js/views/UsersView.vue | 352 ---------- frontend/js/views/bank_account/CreateView.vue | 122 ++++ frontend/js/views/bank_account/EditView.vue | 156 +++++ frontend/js/views/bank_account/ListView.vue | 125 ++++ frontend/js/views/category/CreateView.vue | 173 +++++ frontend/js/views/category/EditView.vue | 300 ++++++++ frontend/js/views/category/ListView.vue | 156 +++++ .../js/views/saving_account/CreateView.vue | 132 ++++ frontend/js/views/saving_account/EditView.vue | 166 +++++ frontend/js/views/saving_account/ListView.vue | 125 ++++ .../ListView.vue} | 273 ++------ frontend/js/views/transaction/ShowView.vue | 73 ++ frontend/js/views/user/CreateView.vue | 125 ++++ frontend/js/views/user/EditView.vue | 168 +++++ frontend/js/views/user/ListView.vue | 134 ++++ 26 files changed, 2425 insertions(+), 1909 deletions(-) create mode 100644 frontend/js/components/crud/DataList.vue create mode 100644 frontend/js/components/crud/FormView.vue create mode 100644 frontend/js/components/crud/FormWidget.vue delete mode 100644 frontend/js/views/BankAccountsView.vue delete mode 100644 frontend/js/views/CategoriesView.vue create mode 100644 frontend/js/views/ComponentView.vue delete mode 100644 frontend/js/views/SavingAccountsView.vue delete mode 100644 frontend/js/views/UsersView.vue create mode 100644 frontend/js/views/bank_account/CreateView.vue create mode 100644 frontend/js/views/bank_account/EditView.vue create mode 100644 frontend/js/views/bank_account/ListView.vue create mode 100644 frontend/js/views/category/CreateView.vue create mode 100644 frontend/js/views/category/EditView.vue create mode 100644 frontend/js/views/category/ListView.vue create mode 100644 frontend/js/views/saving_account/CreateView.vue create mode 100644 frontend/js/views/saving_account/EditView.vue create mode 100644 frontend/js/views/saving_account/ListView.vue rename frontend/js/views/{TransactionsView.vue => transaction/ListView.vue} (61%) create mode 100644 frontend/js/views/transaction/ShowView.vue create mode 100644 frontend/js/views/user/CreateView.vue create mode 100644 frontend/js/views/user/EditView.vue create mode 100644 frontend/js/views/user/ListView.vue diff --git a/database/model/transaction.go b/database/model/transaction.go index 2ab9a57..59f8d2c 100644 --- a/database/model/transaction.go +++ b/database/model/transaction.go @@ -5,6 +5,7 @@ import ( "encoding/csv" "encoding/hex" "errors" + "fmt" "io/ioutil" "regexp" "strconv" @@ -99,6 +100,10 @@ func (t *Transaction) MatchRule(rule CategoryRule) (bool, int) { } } + if match { + fmt.Printf("%+v\n", match) + } + return match, counter } diff --git a/frontend/js/App.vue b/frontend/js/App.vue index 3b9c9e1..ed68623 100644 --- a/frontend/js/App.vue +++ b/frontend/js/App.vue @@ -41,7 +41,7 @@ import {BNavItem} from 'bootstrap-vue-next' class="me-2" :class="route.meta.icon" > - {{ route.name }} + {{ route.meta.label }} diff --git a/frontend/js/components/crud/DataList.vue b/frontend/js/components/crud/DataList.vue new file mode 100644 index 0000000..8376cce --- /dev/null +++ b/frontend/js/components/crud/DataList.vue @@ -0,0 +1,94 @@ + + + diff --git a/frontend/js/components/crud/FormView.vue b/frontend/js/components/crud/FormView.vue new file mode 100644 index 0000000..64df27b --- /dev/null +++ b/frontend/js/components/crud/FormView.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend/js/components/crud/FormWidget.vue b/frontend/js/components/crud/FormWidget.vue new file mode 100644 index 0000000..11d06ec --- /dev/null +++ b/frontend/js/components/crud/FormWidget.vue @@ -0,0 +1,164 @@ + + + diff --git a/frontend/js/components/crud/Header.vue b/frontend/js/components/crud/Header.vue index 74daf36..5149be5 100644 --- a/frontend/js/components/crud/Header.vue +++ b/frontend/js/components/crud/Header.vue @@ -1,6 +1,6 @@ diff --git a/frontend/js/components/crud/FormWidget.vue b/frontend/js/components/crud/FormWidget.vue index 11d06ec..8553eed 100644 --- a/frontend/js/components/crud/FormWidget.vue +++ b/frontend/js/components/crud/FormWidget.vue @@ -31,13 +31,18 @@ :required="field.required" /> -
-
+
+
diff --git a/frontend/js/components/crud/Header.vue b/frontend/js/components/crud/Header.vue index 5149be5..f3f6f27 100644 --- a/frontend/js/components/crud/Header.vue +++ b/frontend/js/components/crud/Header.vue @@ -4,14 +4,17 @@

{{ title }}

-
+
diff --git a/frontend/js/components/crud/Pager.vue b/frontend/js/components/crud/Pager.vue index 5301c3e..78e49be 100644 --- a/frontend/js/components/crud/Pager.vue +++ b/frontend/js/components/crud/Pager.vue @@ -20,8 +20,8 @@ diff --git a/frontend/js/components/dashboard/SavingAccounts.vue b/frontend/js/components/dashboard/SavingAccounts.vue index 6783ccd..f806a00 100644 --- a/frontend/js/components/dashboard/SavingAccounts.vue +++ b/frontend/js/components/dashboard/SavingAccounts.vue @@ -12,10 +12,10 @@ diff --git a/frontend/js/views/FilesView.vue b/frontend/js/views/FilesView.vue index 0c4b32b..7aa4844 100644 --- a/frontend/js/views/FilesView.vue +++ b/frontend/js/views/FilesView.vue @@ -175,7 +175,7 @@ diff --git a/frontend/js/views/transaction/ShowView.vue b/frontend/js/views/transaction/ShowView.vue index a39383f..6e2b236 100644 --- a/frontend/js/views/transaction/ShowView.vue +++ b/frontend/js/views/transaction/ShowView.vue @@ -54,20 +54,13 @@ diff --git a/frontend/js/views/user/CreateView.vue b/frontend/js/views/user/CreateView.vue index 5e37690..4e5686d 100644 --- a/frontend/js/views/user/CreateView.vue +++ b/frontend/js/views/user/CreateView.vue @@ -18,11 +18,14 @@ >
- + - + @@ -33,19 +36,13 @@ diff --git a/frontend/js/components/crud/Pager.vue b/frontend/js/components/crud/Pager.vue index 78e49be..250854f 100644 --- a/frontend/js/components/crud/Pager.vue +++ b/frontend/js/components/crud/Pager.vue @@ -20,7 +20,6 @@ diff --git a/frontend/js/views/bank_account/CreateView.vue b/frontend/js/views/bank_account/CreateView.vue index 694d2c9..3d0c974 100644 --- a/frontend/js/views/bank_account/CreateView.vue +++ b/frontend/js/views/bank_account/CreateView.vue @@ -91,7 +91,7 @@ const createForm = () => { } } -const doSave = (e) => { +const doSave = () => { fetch( `${endpoint}`, createRequestOptions({ diff --git a/frontend/js/views/bank_account/ListView.vue b/frontend/js/views/bank_account/ListView.vue index ac53fe0..484cdd3 100644 --- a/frontend/js/views/bank_account/ListView.vue +++ b/frontend/js/views/bank_account/ListView.vue @@ -42,17 +42,11 @@ diff --git a/frontend/js/components/SortButton.vue b/frontend/js/components/SortButton.vue index b8a68f1..e06c78c 100644 --- a/frontend/js/components/SortButton.vue +++ b/frontend/js/components/SortButton.vue @@ -19,7 +19,28 @@ - - diff --git a/frontend/js/components/crud/Pager.vue b/frontend/js/components/crud/Pager.vue deleted file mode 100644 index 250854f..0000000 --- a/frontend/js/components/crud/Pager.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - diff --git a/frontend/js/components/dashboard/Capital.vue b/frontend/js/components/dashboard/Capital.vue deleted file mode 100644 index 055b06d..0000000 --- a/frontend/js/components/dashboard/Capital.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - - - diff --git a/frontend/js/components/dashboard/CategoriesStats.vue b/frontend/js/components/dashboard/CategoriesStats.vue deleted file mode 100644 index bfec2c2..0000000 --- a/frontend/js/components/dashboard/CategoriesStats.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/frontend/js/components/dashboard/DiffCreditDebit.vue b/frontend/js/components/dashboard/DiffCreditDebit.vue deleted file mode 100644 index 7e81137..0000000 --- a/frontend/js/components/dashboard/DiffCreditDebit.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/frontend/js/components/dashboard/Distribution.vue b/frontend/js/components/dashboard/Distribution.vue deleted file mode 100644 index 9442e13..0000000 --- a/frontend/js/components/dashboard/Distribution.vue +++ /dev/null @@ -1,128 +0,0 @@ - - - diff --git a/frontend/js/components/dashboard/Filters.vue b/frontend/js/components/dashboard/Filters.vue deleted file mode 100644 index be8d7e9..0000000 --- a/frontend/js/components/dashboard/Filters.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/frontend/js/components/dashboard/MonthThresholds.vue b/frontend/js/components/dashboard/MonthThresholds.vue deleted file mode 100644 index 52cedd5..0000000 --- a/frontend/js/components/dashboard/MonthThresholds.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - diff --git a/frontend/js/components/dashboard/SavingAccounts.vue b/frontend/js/components/dashboard/SavingAccounts.vue deleted file mode 100644 index f7a5c0e..0000000 --- a/frontend/js/components/dashboard/SavingAccounts.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - diff --git a/frontend/js/views/DashboardView.vue b/frontend/js/views/DashboardView.vue index 4bd29e2..2788cc1 100644 --- a/frontend/js/views/DashboardView.vue +++ b/frontend/js/views/DashboardView.vue @@ -17,7 +17,7 @@
- {{ i.label }}
- - - - - - -
+ -
+
import { ref, onMounted } from 'vue' -import Header from './../components/crud/Header.vue' +import CrudHeader from './../components/crud/CrudHeader.vue' import { BModal, BButton, diff --git a/frontend/js/views/bank_account/CreateView.vue b/frontend/js/views/bank_account/CreateView.vue index 3d0c974..aba05fd 100644 --- a/frontend/js/views/bank_account/CreateView.vue +++ b/frontend/js/views/bank_account/CreateView.vue @@ -3,7 +3,7 @@ fluid class="p-0" > -
+ -
+ -
+ -
+ -
+ -
+
import { BContainer, BButton, BButtonToolbar } from 'bootstrap-vue-next' -import Header from '../../components/crud/Header.vue' -import Pager from '../../components/crud/Pager.vue' +import CrudHeader from '../../components/crud/CrudHeader.vue' +import CrudPager from '../../components/crud/CrudPager.vue' import DataList from '../../components/crud/DataList.vue' import { ref, onMounted, watch } from 'vue' import { getStorage, saveStorage } from '../../lib/storage' diff --git a/frontend/js/views/category/CreateView.vue b/frontend/js/views/category/CreateView.vue index e111f07..4c8e8a2 100644 --- a/frontend/js/views/category/CreateView.vue +++ b/frontend/js/views/category/CreateView.vue @@ -3,7 +3,7 @@ fluid class="p-0" > -
+ -
+ -
+ -
+ -
+ -
+
-
+ -
+ -
+ -
+ -
+ -
+
import { BContainer, BButton, BButtonToolbar } from 'bootstrap-vue-next' -import Header from '../../components/crud/Header.vue' -import Pager from '../../components/crud/Pager.vue' +import CrudHeader from '../../components/crud/CrudHeader.vue' +import CrudPager from '../../components/crud/CrudPager.vue' import DataList from '../../components/crud/DataList.vue' import { ref, onMounted, watch } from 'vue' import { getStorage, saveStorage } from '../../lib/storage' diff --git a/frontend/js/views/transaction/ListView.vue b/frontend/js/views/transaction/ListView.vue index 500d154..a39b882 100644 --- a/frontend/js/views/transaction/ListView.vue +++ b/frontend/js/views/transaction/ListView.vue @@ -3,7 +3,7 @@ fluid class="p-0" > -
+ -
+
- -
+ -
+ import { BContainer, BButton, BForm, BRow, BCol } from 'bootstrap-vue-next' -import Header from '../../components/crud/Header.vue' +import CrudHeader from '../../components/crud/CrudHeader.vue' import FormView from '../../components/crud/FormView.vue' import { ref, onMounted } from 'vue' import { createRequestOptions } from '../../lib/request' diff --git a/frontend/js/views/user/EditView.vue b/frontend/js/views/user/EditView.vue index 7bddeb2..cad7f67 100644 --- a/frontend/js/views/user/EditView.vue +++ b/frontend/js/views/user/EditView.vue @@ -11,7 +11,7 @@ fluid class="p-0" > -
+ -
+ -
+ -
+
import { BContainer, BButton, BButtonToolbar } from 'bootstrap-vue-next' -import Header from '../../components/crud/Header.vue' -import Pager from '../../components/crud/Pager.vue' +import CrudHeader from '../../components/crud/CrudHeader.vue' +import CrudPager from '../../components/crud/CrudPager.vue' import DataList from '../../components/crud/DataList.vue' import { ref, onMounted, watch } from 'vue' import { getStorage, saveStorage } from '../../lib/storage' From 4918abd5d68de07c82247db9350667c408ff66d6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 26 Mar 2025 11:40:19 +0100 Subject: [PATCH 13/31] fix: fix eslint warnings/errors --- frontend/js/components/CrudFilter.vue | 195 ++++++++++++++++++ frontend/js/components/crud/CrudHeader.vue | 33 +++ frontend/js/components/crud/CrudPager.vue | 63 ++++++ .../js/components/dashboard/CapitalChart.vue | 70 +++++++ .../components/dashboard/CategoriesChart.vue | 140 +++++++++++++ .../js/components/dashboard/DashFilter.vue | 115 +++++++++++ .../dashboard/DiffCreditDebitChart.vue | 41 ++++ .../dashboard/DistributionChart.vue | 145 +++++++++++++ .../dashboard/MonthThresholdsTable.vue | 72 +++++++ .../dashboard/SavingAccountsChart.vue | 37 ++++ 10 files changed, 911 insertions(+) create mode 100644 frontend/js/components/CrudFilter.vue create mode 100644 frontend/js/components/crud/CrudHeader.vue create mode 100644 frontend/js/components/crud/CrudPager.vue create mode 100644 frontend/js/components/dashboard/CapitalChart.vue create mode 100644 frontend/js/components/dashboard/CategoriesChart.vue create mode 100644 frontend/js/components/dashboard/DashFilter.vue create mode 100644 frontend/js/components/dashboard/DiffCreditDebitChart.vue create mode 100644 frontend/js/components/dashboard/DistributionChart.vue create mode 100644 frontend/js/components/dashboard/MonthThresholdsTable.vue create mode 100644 frontend/js/components/dashboard/SavingAccountsChart.vue diff --git a/frontend/js/components/CrudFilter.vue b/frontend/js/components/CrudFilter.vue new file mode 100644 index 0000000..045bd00 --- /dev/null +++ b/frontend/js/components/CrudFilter.vue @@ -0,0 +1,195 @@ + + + diff --git a/frontend/js/components/crud/CrudHeader.vue b/frontend/js/components/crud/CrudHeader.vue new file mode 100644 index 0000000..a4a6b4f --- /dev/null +++ b/frontend/js/components/crud/CrudHeader.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/frontend/js/components/crud/CrudPager.vue b/frontend/js/components/crud/CrudPager.vue new file mode 100644 index 0000000..241eed9 --- /dev/null +++ b/frontend/js/components/crud/CrudPager.vue @@ -0,0 +1,63 @@ + + + diff --git a/frontend/js/components/dashboard/CapitalChart.vue b/frontend/js/components/dashboard/CapitalChart.vue new file mode 100644 index 0000000..70a5047 --- /dev/null +++ b/frontend/js/components/dashboard/CapitalChart.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/frontend/js/components/dashboard/CategoriesChart.vue b/frontend/js/components/dashboard/CategoriesChart.vue new file mode 100644 index 0000000..557a319 --- /dev/null +++ b/frontend/js/components/dashboard/CategoriesChart.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/frontend/js/components/dashboard/DashFilter.vue b/frontend/js/components/dashboard/DashFilter.vue new file mode 100644 index 0000000..2cb7bf4 --- /dev/null +++ b/frontend/js/components/dashboard/DashFilter.vue @@ -0,0 +1,115 @@ + + + diff --git a/frontend/js/components/dashboard/DiffCreditDebitChart.vue b/frontend/js/components/dashboard/DiffCreditDebitChart.vue new file mode 100644 index 0000000..ff1546c --- /dev/null +++ b/frontend/js/components/dashboard/DiffCreditDebitChart.vue @@ -0,0 +1,41 @@ + + + diff --git a/frontend/js/components/dashboard/DistributionChart.vue b/frontend/js/components/dashboard/DistributionChart.vue new file mode 100644 index 0000000..f6c185e --- /dev/null +++ b/frontend/js/components/dashboard/DistributionChart.vue @@ -0,0 +1,145 @@ + + + diff --git a/frontend/js/components/dashboard/MonthThresholdsTable.vue b/frontend/js/components/dashboard/MonthThresholdsTable.vue new file mode 100644 index 0000000..74a0c1c --- /dev/null +++ b/frontend/js/components/dashboard/MonthThresholdsTable.vue @@ -0,0 +1,72 @@ + + + diff --git a/frontend/js/components/dashboard/SavingAccountsChart.vue b/frontend/js/components/dashboard/SavingAccountsChart.vue new file mode 100644 index 0000000..966e1da --- /dev/null +++ b/frontend/js/components/dashboard/SavingAccountsChart.vue @@ -0,0 +1,37 @@ + + + From f9fb6e578612666d5955f32084fcf03b20a1af57 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 26 Mar 2025 12:33:56 +0100 Subject: [PATCH 14/31] config(prettierrc): set printWidth --- .prettierrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc.json b/.prettierrc.json index 280fb28..a2065a9 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -3,5 +3,6 @@ "bracketSameLine": false, "semi": false, "singleQuote": true, - "singleAttributePerLine": true + "singleAttributePerLine": true, + "printWidth": 160 } From 3ca85251f4bfbfaa7319ee8da8a7a291131290c8 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 26 Mar 2025 12:34:05 +0100 Subject: [PATCH 15/31] apply linter --- frontend/js/App.vue | 10 +--- frontend/js/chart/debitAverage.js | 3 +- frontend/js/chart/distribution.js | 18 ++------ frontend/js/chart/monthThreshold.js | 5 +- frontend/js/components/CrudFilter.vue | 19 ++------ frontend/js/components/crud/CrudHeader.vue | 2 +- frontend/js/components/crud/FormWidget.vue | 16 ++----- .../components/dashboard/CategoriesChart.vue | 24 ++-------- .../js/components/dashboard/DashFilter.vue | 7 +-- .../dashboard/DistributionChart.vue | 4 +- .../dashboard/MonthThresholdsTable.vue | 10 ++-- .../dashboard/SavingAccountsChart.vue | 2 +- frontend/js/lib/renderers.js | 9 +--- frontend/js/main.js | 25 +--------- frontend/js/views/DashboardView.vue | 46 +++++-------------- frontend/js/views/FilesView.vue | 18 +------- frontend/js/views/bank_account/CreateView.vue | 9 +--- frontend/js/views/bank_account/EditView.vue | 9 +--- frontend/js/views/category/CreateView.vue | 21 ++------- frontend/js/views/category/EditView.vue | 42 +++-------------- frontend/js/views/category/ListView.vue | 14 ++---- .../js/views/saving_account/CreateView.vue | 9 +--- frontend/js/views/saving_account/EditView.vue | 9 +--- frontend/js/views/transaction/ListView.vue | 17 +------ frontend/js/views/user/EditView.vue | 9 +--- frontend/scss/main.scss | 11 +---- 26 files changed, 61 insertions(+), 307 deletions(-) diff --git a/frontend/js/App.vue b/frontend/js/App.vue index 0f50bb3..5718658 100644 --- a/frontend/js/App.vue +++ b/frontend/js/App.vue @@ -20,15 +20,7 @@ import { BNavItem } from 'bootstrap-vue-next'
@@ -33,18 +31,14 @@ /> import { ref, onMounted } from 'vue' -import { - BFormGroup, - BFormInput, - BFormSelect, - BButton, -} from 'bootstrap-vue-next' +import { BFormGroup, BFormInput, BFormSelect, BButton } from 'bootstrap-vue-next' const emit = defineEmits(['update']) const props = defineProps({ diff --git a/frontend/js/components/crud/CrudHeader.vue b/frontend/js/components/crud/CrudHeader.vue index a4a6b4f..e9f0e37 100644 --- a/frontend/js/components/crud/CrudHeader.vue +++ b/frontend/js/components/crud/CrudHeader.vue @@ -18,7 +18,7 @@ defineProps({ title: { type: [String, null], required: true, - } + }, }) diff --git a/frontend/js/components/crud/FormWidget.vue b/frontend/js/components/crud/FormWidget.vue index 8553eed..400dce0 100644 --- a/frontend/js/components/crud/FormWidget.vue +++ b/frontend/js/components/crud/FormWidget.vue @@ -35,9 +35,7 @@ v-if="field.widget === 'rules'" id="rules" > -
+
@@ -130,13 +126,7 @@ diff --git a/frontend/js/components/dashboard/SavingAccountsChart.vue b/frontend/js/components/dashboard/SavingAccountsChart.vue index 966e1da..f4c87ba 100644 --- a/frontend/js/components/dashboard/SavingAccountsChart.vue +++ b/frontend/js/components/dashboard/SavingAccountsChart.vue @@ -20,7 +20,7 @@ defineProps({ data: { type: Array, required: true, - } + }, }) const options = () => { diff --git a/frontend/js/lib/renderers.js b/frontend/js/lib/renderers.js index 12ea285..3c78c80 100644 --- a/frontend/js/lib/renderers.js +++ b/frontend/js/lib/renderers.js @@ -62,11 +62,4 @@ const renderLabelWithSum = (label, rows, key) => { return `${label}
${renderEuro(sum)}` } -export { - renderDate, - renderDateTime, - renderCategory, - renderBankAccount, - renderEuro, - renderLabelWithSum, -} +export { renderDate, renderDateTime, renderCategory, renderBankAccount, renderEuro, renderLabelWithSum } diff --git a/frontend/js/main.js b/frontend/js/main.js index 285c146..e420f00 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -3,30 +3,9 @@ import { createApp } from 'vue' import App from './App.vue' import router from './router' import { createBootstrap } from 'bootstrap-vue-next' -import { - Chart as ChartJS, - Title, - Tooltip, - Legend, - BarElement, - CategoryScale, - LinearScale, - ArcElement, - LineElement, - PointElement, -} from 'chart.js' +import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, ArcElement, LineElement, PointElement } from 'chart.js' -ChartJS.register( - Title, - Tooltip, - Legend, - BarElement, - CategoryScale, - LinearScale, - ArcElement, - LineElement, - PointElement, -) +ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, ArcElement, LineElement, PointElement) const app = createApp(App) diff --git a/frontend/js/views/DashboardView.vue b/frontend/js/views/DashboardView.vue index 2788cc1..b5976e1 100644 --- a/frontend/js/views/DashboardView.vue +++ b/frontend/js/views/DashboardView.vue @@ -1,13 +1,6 @@