diff --git a/compose.yaml b/compose.yaml index e33152e..fd5c804 100644 --- a/compose.yaml +++ b/compose.yaml @@ -11,5 +11,6 @@ services: - '5432:5432' volumes: - 'db-data:/var/lib/postgresql/data/' + - '/etc/localtime:/etc/localtime:ro' volumes: db-data: diff --git a/db.go b/db.go index 4274fd1..fd243d5 100644 --- a/db.go +++ b/db.go @@ -3,7 +3,9 @@ package main import ( "context" "fmt" + "log" + "git.agecem.com/bottin/agendas/queries" "github.com/jackc/pgx/v5/pgxpool" ) @@ -27,8 +29,13 @@ func (d DBClient) Ping(ctx context.Context) error { func (d DBClient) Init(ctx context.Context) error { //TODO check context is not closed //TODO check *DB is not nil - //TODO Init - return fmt.Errorf("db: Init not implemented") + log.Println("warning: DBClient [Init] not properly checked") + // Init + if _, err := d.Pool.Exec(ctx, queries.SQLSchema()); err != nil { + return err + } + + return nil } func (d DBClient) CreateTransaction(ctx context.Context, transaction Transaction) error { diff --git a/go.mod b/go.mod index 089ecbd..6d97f24 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23.4 require ( codeberg.org/vlbeaudoin/voki/v3 v3.0.1 git.agecem.com/bottin/bottin/v10 v10.4.1 + github.com/jackc/pgx/v5 v5.7.1 github.com/labstack/echo/v4 v4.13.3 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -18,7 +19,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/magiconair/properties v1.8.7 // indirect diff --git a/handler.go b/handler.go index a771687..801f8dd 100644 --- a/handler.go +++ b/handler.go @@ -17,6 +17,7 @@ func UIIndex(ctx context.Context, bottinClient *bottin.APIClient, dbClient *DBCl Error string BottinHealthResponse bottin.ReadHealthResponse IsDBUp bool + Result string } return c.Render(http.StatusOK, "index", func() (d data) { @@ -62,47 +63,6 @@ func UIIndex(ctx context.Context, bottinClient *bottin.APIClient, dbClient *DBCl } } -func UIReadMembre(ctx context.Context, bottinClient *bottin.APIClient) echo.HandlerFunc { - return func(c echo.Context) error { - type data struct { - Error string - BottinMembreResponse bottin.ReadMembreResponse - } - - return c.Render(http.StatusOK, "index", func() (d data) { - if err := func() error { - select { - case <-ctx.Done(): - return fmt.Errorf("Impossible de contacter le serveur: %s", ctx.Err()) - default: - // Check client - if bottinClient == nil { - return fmt.Errorf("Impossible de contacter le serveur, le client API est nil") - } - - var err error - - // Check membre - d.BottinMembreResponse, err = bottinClient.ReadMembre(ctx, c.QueryParam("m")) - if err != nil { - return err - } - - // No errors - return nil - } - }(); err != nil { - // Send error to user - d.Error = err.Error() - - // Log error - log.Println("err:", d.Error) - } - return - }()) - } -} - /* UICreateTransaction gère la création des transactions @@ -113,9 +73,9 @@ TODO: func UICreateTransaction(ctx context.Context, cfg Config, bottinClient *bottin.APIClient, dbClient *DBClient) echo.HandlerFunc { return func(c echo.Context) error { type data struct { - BottinHealth bottin.ReadHealthResponse - Error string - Result string + Error string + Result string + //BottinHealth bottin.ReadHealthResponse } return c.Render(http.StatusOK, "index", func() (d data) { @@ -124,12 +84,14 @@ func UICreateTransaction(ctx context.Context, cfg Config, bottinClient *bottin.A return fmt.Errorf("Cannot operate on nil *bottin.APIClient") } - bottinReadHealthResponse, err := bottinClient.ReadHealth(ctx) - if err != nil { - return err - } + /* + bottinReadHealthResponse, err := bottinClient.ReadHealth(ctx) + if err != nil { + return err + } - d.BottinHealth = bottinReadHealthResponse + d.BottinHealth = bottinReadHealthResponse + */ isPerpetual := c.FormValue("is_perpetual") == "on" membreID := c.FormValue("membre_id") diff --git a/queries/queries.go b/queries/queries.go new file mode 100644 index 0000000..3f33b1e --- /dev/null +++ b/queries/queries.go @@ -0,0 +1,10 @@ +package queries + +import _ "embed" + +//go:embed schema.sql +var sqlSchema string + +func SQLSchema() string { + return sqlSchema +} diff --git a/queries/schema.sql b/queries/schema.sql new file mode 100644 index 0000000..3eb2487 --- /dev/null +++ b/queries/schema.sql @@ -0,0 +1,7 @@ +-- Schema +CREATE TABLE IF NOT EXISTS transactions ( + given_at TIMESTAMP DEFAULT current_timestamp, + membre_id VARCHAR(7) NOT NULL CHECK (length(membre_id) > 0), + is_perpetual BOOLEAN NOT NULL, + PRIMARY KEY (membre_id, is_perpetual) +); diff --git a/server.go b/server.go index a414744..a9a4117 100644 --- a/server.go +++ b/server.go @@ -25,6 +25,10 @@ func RunServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient, return fmt.Errorf("nil dbClient") } + if err := dbClient.Init(ctx); err != nil { + return err + } + e := echo.New() r := ui.NewRenderer() @@ -42,7 +46,7 @@ func RunServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient, return fmt.Errorf("UI requires at least one credential (config key `Credentials` of type map[string]string)") } - e.Use(middleware.BasicAuth( + e.Pre(middleware.BasicAuth( func(username, password string, c echo.Context) (bool, error) { for validUser, validPass := range cfg.Credentials { userOK := subtle.ConstantTimeCompare([]byte(username), []byte(validUser)) == 1 @@ -62,8 +66,6 @@ func RunServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient, //e.GET("/transaction/", UIReadTransaction e.POST("/transaction/", UICreateTransaction(ctx, cfg, bottinClient, dbClient)) - //e.GET("/membre/", UIReadMembre(ctx, bottinClient)) - address := fmt.Sprintf(":%d", cfg.Port) if cfg.TLS.Enabled { diff --git a/ui/index.html b/ui/index.html index bdf4e1c..a10c75a 100644 --- a/ui/index.html +++ b/ui/index.html @@ -112,8 +112,8 @@ button { - {{ if .Error }}

Erreur: {{ .Error }}

{{ end }} -

{{ .Result }}

+ {{ if .Error }}

Erreur: {{ .Error }}

{{ end }} + {{ if .Result }}

{{ .Result }}

{{ end }}