diff --git a/.air.toml b/.air.toml index 921489b..b268d61 100644 --- a/.air.toml +++ b/.air.toml @@ -5,7 +5,7 @@ tmp_dir = "tmp" [build] args_bin = [] bin = "./tmp/main" - cmd = "go build -o ./tmp/main ./cmd/reshoot" + cmd = "go build -o ./tmp/main ./cmd/projectreshoot" delay = 1000 exclude_dir = [] exclude_file = [] diff --git a/.gitignore b/.gitignore index 9d8ebf9..33692cc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ server.log bin/ tmp/ static/css/output.css -view/**/*_templ.go -view/**/*_templ.txt +internal/view/**/*_templ.go +internal/view/**/*_templ.txt diff --git a/Makefile b/Makefile index 78aa20a..d715556 100644 --- a/Makefile +++ b/Makefile @@ -8,26 +8,18 @@ build: tailwindcss -i ./pkg/embedfs/files/css/input.css -o ./pkg/embedfs/files/css/output.css && \ go mod tidy && \ templ generate && \ - go generate ./cmd/projectreshoot && \ - go build -ldflags="-w -s" -o ./bin/${BINARY_NAME}${SUFFIX} ./cmd/projectreshoot + go generate ./cmd/${BINARY_NAME} && \ + go build -ldflags="-w -s" -o ./bin/${BINARY_NAME}${SUFFIX} ./cmd/${BINARY_NAME} + +run: + make build + ./bin/${BINARY_NAME}${SUFFIX} dev: templ generate --watch &\ air &\ tailwindcss -i ./pkg/embedfs/files/css/input.css -o ./pkg/embedfs/files/css/output.css --watch -tester: - go mod tidy && \ - go run . --port 3232 --tester --loglevel trace - -test: - go mod tidy && \ - templ generate && \ - go generate ./cmd/projectreshoot && \ - go test ./cmd/projectreshoot - go test ./pkg/db - go test ./internal/middleware - clean: go clean diff --git a/cmd/projectreshoot/dbconn.go b/cmd/projectreshoot/dbconn.go index 650f8c1..c6b800d 100644 --- a/cmd/projectreshoot/dbconn.go +++ b/cmd/projectreshoot/dbconn.go @@ -1,37 +1,53 @@ package main import ( - "projectreshoot/pkg/config" - "projectreshoot/pkg/db" - "projectreshoot/pkg/tests" + "database/sql" + "fmt" "strconv" "github.com/pkg/errors" - "github.com/rs/zerolog" + + _ "github.com/mattn/go-sqlite3" ) -func setupDBConn( - args map[string]string, - logger *zerolog.Logger, - config *config.Config, -) (*db.SafeConn, error) { - if args["test"] == "true" { - logger.Debug().Msg("Server in test mode, using test database") - ver, err := strconv.ParseInt(config.DBName, 10, 0) - if err != nil { - return nil, errors.Wrap(err, "strconv.ParseInt") - } - wconn, rconn, err := tests.SetupTestDB(ver) - if err != nil { - return nil, errors.Wrap(err, "tests.SetupTestDB") - } - conn := db.MakeSafe(wconn, rconn, logger) - return conn, nil - } else { - conn, err := db.ConnectToDatabase(config.DBName, logger) - if err != nil { - return nil, errors.Wrap(err, "db.ConnectToDatabase") - } - return conn, nil +func setupDBConn(dbName string) (*sql.DB, error) { + opts := "_journal_mode=WAL&_synchronous=NORMAL&_txlock=IMMEDIATE" + file := fmt.Sprintf("file:%s.db?%s", dbName, opts) + conn, err := sql.Open("sqlite3", file) + if err != nil { + return nil, errors.Wrap(err, "sql.Open") } + err = checkDBVersion(conn, dbName) + if err != nil { + return nil, errors.Wrap(err, "checkDBVersion") + } + return conn, nil +} + +// Check the database version +func checkDBVersion(db *sql.DB, dbName string) error { + expectVer, err := strconv.Atoi(dbName) + if err != nil { + return errors.Wrap(err, "strconv.Atoi") + } + query := `SELECT version_id FROM goose_db_version WHERE is_applied = 1 + ORDER BY version_id DESC LIMIT 1` + rows, err := db.Query(query) + if err != nil { + return errors.Wrap(err, "db.Query") + } + defer rows.Close() + if rows.Next() { + var version int + err = rows.Scan(&version) + if err != nil { + return errors.Wrap(err, "rows.Scan") + } + if version != expectVer { + return errors.New("Version mismatch") + } + } else { + return errors.New("No version found") + } + return nil } diff --git a/cmd/projectreshoot/main_test.go b/cmd/projectreshoot/main_test.go deleted file mode 100644 index a97a5ae..0000000 --- a/cmd/projectreshoot/main_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package main - -import ( - "bytes" - "context" - "fmt" - "net/http" - "os" - "strings" - "syscall" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func Test_main(t *testing.T) { - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) - t.Cleanup(cancel) - args := map[string]string{"test": "true"} - var stdout bytes.Buffer - os.Setenv("SECRET_KEY", ".") - os.Setenv("TMDB_API_TOKEN", ".") - os.Setenv("HOST", "127.0.0.1") - os.Setenv("PORT", "3232") - runSrvErr := make(chan error) - go func() { - if err := run(ctx, &stdout, args); err != nil { - runSrvErr <- err - return - } - }() - - go func() { - err := waitForReady(ctx, 10*time.Second, "http://127.0.0.1:3232/healthz") - if err != nil { - runSrvErr <- err - return - } - runSrvErr <- nil - }() - select { - case err := <-runSrvErr: - if err != nil { - t.Fatalf("Error starting test server: %s", err) - return - } - t.Log("Test server started") - } - - t.Run("SIGUSR1 puts database into global lock", func(t *testing.T) { - done := make(chan bool) - go func() { - expected := "Global database lock acquired" - for { - if strings.Contains(stdout.String(), expected) { - done <- true - return - } - time.Sleep(100 * time.Millisecond) - } - }() - - proc, err := os.FindProcess(os.Getpid()) - require.NoError(t, err) - proc.Signal(syscall.SIGUSR1) - - select { - case <-done: - t.Log("found") - case <-time.After(250 * time.Millisecond): - t.Errorf("Not found") - } - }) - - t.Run("SIGUSR2 releases database global lock", func(t *testing.T) { - done := make(chan bool) - go func() { - expected := "Global database lock released" - for { - if strings.Contains(stdout.String(), expected) { - done <- true - return - } - time.Sleep(100 * time.Millisecond) - } - }() - - proc, err := os.FindProcess(os.Getpid()) - require.NoError(t, err) - proc.Signal(syscall.SIGUSR2) - - select { - case <-done: - t.Log("found") - case <-time.After(250 * time.Millisecond): - t.Errorf("Not found") - } - }) -} - -func waitForReady( - ctx context.Context, - timeout time.Duration, - endpoint string, -) error { - client := http.Client{} - startTime := time.Now() - for { - req, err := http.NewRequestWithContext( - ctx, - http.MethodGet, - endpoint, - nil, - ) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - - resp, err := client.Do(req) - if err != nil { - fmt.Printf("Error making request: %s\n", err.Error()) - time.Sleep(250 * time.Millisecond) - continue - } - if resp.StatusCode == http.StatusOK { - fmt.Println("Endpoint is ready!") - resp.Body.Close() - return nil - } - resp.Body.Close() - - select { - case <-ctx.Done(): - return ctx.Err() - default: - if time.Since(startTime) >= timeout { - return fmt.Errorf("timeout reached while waiting for endpoint") - } - // wait a little while between checks - time.Sleep(250 * time.Millisecond) - } - } -} diff --git a/cmd/projectreshoot/run.go b/cmd/projectreshoot/run.go index ec530ac..9b9841c 100644 --- a/cmd/projectreshoot/run.go +++ b/cmd/projectreshoot/run.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "git.haelnorr.com/haelnorr/golibh/logger" "io" "net/http" "os" @@ -14,6 +13,9 @@ import ( "sync" "time" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" + "github.com/pkg/errors" ) @@ -38,7 +40,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { // Setup the logfile var logfile *os.File = nil if config.LogOutput == "both" || config.LogOutput == "file" { - logfile, err = logging.GetLogFile(config.LogDir) + logfile, err = hlog.NewLogFile(config.LogDir) if err != nil { return errors.Wrap(err, "logging.GetLogFile") } @@ -52,7 +54,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { } // Setup the logger - logger, err := logging.GetLogger( + logger, err := hlog.NewLogger( config.LogLevel, consoleWriter, logfile, @@ -65,7 +67,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { // Setup the database connection logger.Debug().Msg("Config loaded and logger started") logger.Debug().Msg("Connecting to database") - conn, err := setupDBConn(args, logger, config) + conn, err := setupDBConn(config.DBName) if err != nil { return errors.Wrap(err, "setupDBConn") } @@ -78,18 +80,22 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { return errors.Wrap(err, "getStaticFiles") } - logger.Debug().Msg("Setting up HTTP server") - httpServer := httpserver.NewServer(config, logger, conn, &staticFS, &maint) + // Setup TokenGenerator + logger.Debug().Msg("Creating TokenGenerator") + tokenGen, err := jwt.CreateGenerator( + config.AccessTokenExpiry, + config.RefreshTokenExpiry, + config.TokenFreshTime, + config.TrustedHost, + config.SecretKey, + conn, + ) - // Runs function for testing in dev if --tester flag true - if args["tester"] == "true" { - logger.Debug().Msg("Running tester function") - test(config, logger, conn, httpServer) - return nil - } + logger.Debug().Msg("Setting up HTTP server") + httpServer := httpserver.NewServer(config, logger, conn, tokenGen, &staticFS, &maint) // Setups a channel to listen for os.Signal - handleMaintSignals(conn, config, httpServer, logger) + handleMaintSignals(httpServer, logger) // Runs the http server logger.Debug().Msg("Starting up the HTTP server") @@ -102,9 +108,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { // Handles graceful shutdown var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { <-ctx.Done() shutdownCtx := context.Background() shutdownCtx, cancel := context.WithTimeout(shutdownCtx, 10*time.Second) @@ -112,7 +116,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string) error { if err := httpServer.Shutdown(shutdownCtx); err != nil { logger.Error().Err(err).Msg("Error shutting down server") } - }() + }) wg.Wait() logger.Info().Msg("Shutting down") return nil diff --git a/cmd/projectreshoot/signals.go b/cmd/projectreshoot/signals.go index e608cc3..10566b0 100644 --- a/cmd/projectreshoot/signals.go +++ b/cmd/projectreshoot/signals.go @@ -4,21 +4,16 @@ import ( "net/http" "os" "os/signal" - "projectreshoot/pkg/config" - "projectreshoot/pkg/db" "sync/atomic" "syscall" - "time" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" ) // Handle SIGUSR1 and SIGUSR2 syscalls to toggle maintenance mode func handleMaintSignals( - conn *db.SafeConn, - config *config.Config, srv *http.Server, - logger *zerolog.Logger, + logger *hlog.Logger, ) { logger.Debug().Msg("Starting signal listener") ch := make(chan os.Signal, 1) @@ -33,14 +28,10 @@ func handleMaintSignals( if atomic.LoadUint32(&maint) != 1 { atomic.StoreUint32(&maint, 1) logger.Info().Msg("Signal received: Starting maintenance") - logger.Info().Msg("Attempting to acquire database lock") - conn.Pause(config.DBLockTimeout * time.Second) } case syscall.SIGUSR2: if atomic.LoadUint32(&maint) != 0 { logger.Info().Msg("Signal received: Maintenance over") - logger.Info().Msg("Releasing database lock") - conn.Resume() atomic.StoreUint32(&maint, 0) } } diff --git a/cmd/projectreshoot/tester.go b/cmd/projectreshoot/tester.go deleted file mode 100644 index 3932bf7..0000000 --- a/cmd/projectreshoot/tester.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "net/http" - - "projectreshoot/pkg/config" - "projectreshoot/pkg/db" - "projectreshoot/pkg/tmdb" - - "github.com/rs/zerolog" -) - -// This function will only be called if the --test commandline flag is set. -// After the function finishes the application will close. -// Running command `make tester` will run the test using port 3232 to avoid -// conflicts on the default 3333. Useful for testing things out during dev. -// If you add code here, remember to run: -// `git update-index --assume-unchanged tester.go` to avoid tracking changes -func test( - config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, - srv *http.Server, -) { - query := "a few good men" - search, err := tmdb.SearchMovies(config.TMDBToken, query, false, 1) - if err != nil { - logger.Error().Err(err).Msg("error occured") - return - } - logger.Info().Interface("results", search).Msg("search results received") -} diff --git a/go.mod b/go.mod index 55987f6..b010702 100644 --- a/go.mod +++ b/go.mod @@ -3,36 +3,35 @@ module projectreshoot go 1.25.5 require ( - github.com/a-h/templ v0.3.833 - github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/google/uuid v1.6.0 + git.haelnorr.com/h/golib/hlog v0.9.0 + git.haelnorr.com/h/golib/jwt v0.9.0 + git.haelnorr.com/h/golib/tmdb v0.8.0 + github.com/a-h/templ v0.3.977 github.com/joho/godotenv v1.5.1 github.com/mattn/go-sqlite3 v1.14.24 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.24.1 - github.com/rs/zerolog v1.34.0 - github.com/stretchr/testify v1.10.0 golang.org/x/crypto v0.33.0 modernc.org/sqlite v1.35.0 ) +replace git.haelnorr.com/h/golib/jwt v0.9.0 => /home/haelnorr/projects/golib/jwt + require ( - git.haelnorr.com/haelnorr/golibh/logger v0.0.0-20251231092003-201af4af7a28 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mfridman/interpolate v0.0.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rs/zerolog v1.34.0 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect modernc.org/libc v1.61.13 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.8.2 // indirect diff --git a/go.sum b/go.sum index e93d55f..90de7ef 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ -git.haelnorr.com/haelnorr/golibh/logger v0.0.0-20251231092003-201af4af7a28 h1:9Kja2VpN9TU+7NWefoSW40jdBQaLEC2Gklo3uWoWGSk= -git.haelnorr.com/haelnorr/golibh/logger v0.0.0-20251231092003-201af4af7a28/go.mod h1:rn805r6IrjzM/90X8pr9ulkBKqCg01YueivQZNMb/IY= -github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU= -github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk= +git.haelnorr.com/h/golib/hlog v0.9.0 h1:ib8n2MdmiRK2TF067p220kXmhDe9aAnlcsgpuv+QpvE= +git.haelnorr.com/h/golib/hlog v0.9.0/go.mod h1:oOlzb8UVHUYP1k7dN5PSJXVskAB2z8EYgRN85jAi0Zk= +git.haelnorr.com/h/golib/tmdb v0.8.0 h1:OQ6M2TB8FHm8fJD7/ebfWm63Duzfp0kmFX9genEig34= +git.haelnorr.com/h/golib/tmdb v0.8.0/go.mod h1:mGKYa3o3z0IsQ5EO3MPmnL2Bwl2sSMsUHXVgaIGR7Z0= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/a-h/templ v0.3.977 h1:kiKAPXTZE2Iaf8JbtM21r54A8bCNsncrfnokZZSrSDg= +github.com/a-h/templ v0.3.977/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= @@ -18,11 +22,6 @@ 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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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= @@ -44,36 +43,30 @@ github.com/pressly/goose/v3 v3.24.1 h1:bZmxRco2uy5uu5Ng1MMVEfYsFlrMJI+e/VMXHQ3C4 github.com/pressly/goose/v3 v3.24.1/go.mod h1:rEWreU9uVtt0DHCyLzF9gRcWiiTF/V+528DV+4DORug= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -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= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= diff --git a/internal/handler/account.go b/internal/handler/account.go index fcb97e8..ee8e622 100644 --- a/internal/handler/account.go +++ b/internal/handler/account.go @@ -2,6 +2,7 @@ package handler import ( "context" + "database/sql" "net/http" "time" @@ -10,10 +11,10 @@ import ( "projectreshoot/internal/view/page" "projectreshoot/pkg/contexts" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" + + "git.haelnorr.com/h/golib/hlog" "github.com/pkg/errors" - "github.com/rs/zerolog" ) // Renders the account page on the 'General' subpage @@ -44,8 +45,8 @@ func AccountSubpage() http.Handler { // Handles a request to change the users username func ChangeUsername( - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -53,7 +54,7 @@ func ChangeUsername( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { logger.Warn().Err(err).Msg("Error updating username") w.WriteHeader(http.StatusServiceUnavailable) @@ -61,7 +62,7 @@ func ChangeUsername( } r.ParseForm() newUsername := r.FormValue("username") - unique, err := models.CheckUsernameUnique(ctx, tx, newUsername) + unique, err := models.CheckUsernameUnique(tx, newUsername) if err != nil { tx.Rollback() logger.Error().Err(err).Msg("Error updating username") @@ -75,7 +76,7 @@ func ChangeUsername( return } user := contexts.GetUser(r.Context()) - err = user.ChangeUsername(ctx, tx, newUsername) + err = user.ChangeUsername(tx, newUsername) if err != nil { tx.Rollback() logger.Error().Err(err).Msg("Error updating username") @@ -90,8 +91,8 @@ func ChangeUsername( // Handles a request to change the users bio func ChangeBio( - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -99,7 +100,7 @@ func ChangeBio( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { logger.Warn().Err(err).Msg("Error updating bio") w.WriteHeader(http.StatusServiceUnavailable) @@ -115,7 +116,7 @@ func ChangeBio( return } user := contexts.GetUser(r.Context()) - err = user.ChangeBio(ctx, tx, newBio) + err = user.ChangeBio(tx, newBio) if err != nil { tx.Rollback() logger.Error().Err(err).Msg("Error updating bio") @@ -144,8 +145,8 @@ func validateChangePassword( // Handles a request to change the users password func ChangePassword( - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -153,7 +154,7 @@ func ChangePassword( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { logger.Warn().Err(err).Msg("Error updating password") w.WriteHeader(http.StatusServiceUnavailable) @@ -166,7 +167,7 @@ func ChangePassword( return } user := contexts.GetUser(r.Context()) - err = user.SetPassword(ctx, tx, newPass) + err = user.SetPassword(tx, newPass) if err != nil { tx.Rollback() logger.Error().Err(err).Msg("Error updating password") diff --git a/internal/handler/login.go b/internal/handler/login.go index 8157db3..fda9698 100644 --- a/internal/handler/login.go +++ b/internal/handler/login.go @@ -2,6 +2,7 @@ package handler import ( "context" + "database/sql" "net/http" "time" @@ -10,27 +11,26 @@ import ( "projectreshoot/internal/view/page" "projectreshoot/pkg/config" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" - "github.com/rs/zerolog" ) // Validates the username matches a user in the database and the password // is correct. Returns the corresponding user func validateLogin( - ctx context.Context, - tx db.SafeTX, + tx *sql.Tx, r *http.Request, ) (*models.User, error) { formUsername := r.FormValue("username") formPassword := r.FormValue("password") - user, err := models.GetUserFromUsername(ctx, tx, formUsername) + user, err := models.GetUserFromUsername(tx, formUsername) if err != nil { return nil, errors.Wrap(err, "db.GetUserFromUsername") } - err = user.CheckPassword(formPassword) + err = user.CheckPassword(tx, formPassword) if err != nil { return nil, errors.New("Username or password incorrect") } @@ -52,8 +52,9 @@ func checkRememberMe(r *http.Request) bool { // template for user feedback func LoginRequest( config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -61,14 +62,14 @@ func LoginRequest( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { logger.Warn().Err(err).Msg("Failed to set token cookies") w.WriteHeader(http.StatusServiceUnavailable) return } r.ParseForm() - user, err := validateLogin(ctx, tx, r) + user, err := validateLogin(tx, r) if err != nil { tx.Rollback() if err.Error() != "Username or password incorrect" { @@ -81,7 +82,7 @@ func LoginRequest( } rememberMe := checkRememberMe(r) - err = cookies.SetTokenCookies(w, r, config, user, true, rememberMe) + err = cookies.SetTokenCookies(w, r, config, tokenGen, user, true, rememberMe) if err != nil { tx.Rollback() w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/handler/logout.go b/internal/handler/logout.go index 715c81f..3180dfa 100644 --- a/internal/handler/logout.go +++ b/internal/handler/logout.go @@ -2,26 +2,25 @@ package handler import ( "context" + "database/sql" "net/http" "strings" "time" - "projectreshoot/pkg/config" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" - "projectreshoot/pkg/jwt" + + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" - "github.com/rs/zerolog" ) func revokeAccess( - config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, atStr string, ) error { - aT, err := jwt.ParseAccessToken(config, ctx, tx, atStr) + aT, err := tokenGen.ValidateAccess(tx, atStr) if err != nil { if strings.Contains(err.Error(), "Token is expired") || strings.Contains(err.Error(), "Token has been revoked") { @@ -29,7 +28,7 @@ func revokeAccess( } return errors.Wrap(err, "jwt.ParseAccessToken") } - err = jwt.RevokeToken(ctx, tx, aT) + err = aT.Revoke(tx) if err != nil { return errors.Wrap(err, "jwt.RevokeToken") } @@ -37,12 +36,11 @@ func revokeAccess( } func revokeRefresh( - config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, rtStr string, ) error { - rT, err := jwt.ParseRefreshToken(config, ctx, tx, rtStr) + rT, err := tokenGen.ValidateRefresh(tx, rtStr) if err != nil { if strings.Contains(err.Error(), "Token is expired") || strings.Contains(err.Error(), "Token has been revoked") { @@ -50,7 +48,7 @@ func revokeRefresh( } return errors.Wrap(err, "jwt.ParseRefreshToken") } - err = jwt.RevokeToken(ctx, tx, rT) + err = rT.Revoke(tx) if err != nil { return errors.Wrap(err, "jwt.RevokeToken") } @@ -59,20 +57,19 @@ func revokeRefresh( // Retrieve and revoke the user's tokens func revokeTokens( - config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, r *http.Request, ) error { // get the tokens from the cookies atStr, rtStr := cookies.GetTokenStrings(r) // revoke the refresh token first as the access token expires quicker // only matters if there is an error revoking the tokens - err := revokeRefresh(config, ctx, tx, rtStr) + err := revokeRefresh(tokenGen, tx, rtStr) if err != nil { return errors.Wrap(err, "revokeRefresh") } - err = revokeAccess(config, ctx, tx, atStr) + err = revokeAccess(tokenGen, tx, atStr) if err != nil { return errors.Wrap(err, "revokeAccess") } @@ -81,25 +78,25 @@ func revokeTokens( // Handle a logout request func Logout( - config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, + logger *hlog.Logger, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second) defer cancel() - // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { - logger.Warn().Err(err).Msg("Error occured on user logout") - w.WriteHeader(http.StatusServiceUnavailable) + logger.Error().Err(err).Msg("Failed to start database transaction") + w.WriteHeader(http.StatusInternalServerError) return } - err = revokeTokens(config, ctx, tx, r) + defer tx.Rollback() + + err = revokeTokens(tokenGen, tx, r) if err != nil { - tx.Rollback() logger.Error().Err(err).Msg("Error occured on user logout") w.WriteHeader(http.StatusInternalServerError) return diff --git a/internal/handler/movie.go b/internal/handler/movie.go index c4b286e..ca352fa 100644 --- a/internal/handler/movie.go +++ b/internal/handler/movie.go @@ -4,14 +4,14 @@ import ( "net/http" "projectreshoot/internal/view/page" "projectreshoot/pkg/config" - "projectreshoot/pkg/tmdb" "strconv" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/tmdb" ) func Movie( - logger *zerolog.Logger, + logger *hlog.Logger, config *config.Config, ) http.Handler { return http.HandlerFunc( diff --git a/internal/handler/movie_search.go b/internal/handler/movie_search.go index aaa425a..dfa7b98 100644 --- a/internal/handler/movie_search.go +++ b/internal/handler/movie_search.go @@ -5,13 +5,13 @@ import ( "projectreshoot/internal/view/component/search" "projectreshoot/internal/view/page" "projectreshoot/pkg/config" - "projectreshoot/pkg/tmdb" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/tmdb" ) func SearchMovies( - logger *zerolog.Logger, + logger *hlog.Logger, config *config.Config, ) http.Handler { return http.HandlerFunc( diff --git a/internal/handler/reauthenticatate.go b/internal/handler/reauthenticatate.go index b3e8189..aa7b0b4 100644 --- a/internal/handler/reauthenticatate.go +++ b/internal/handler/reauthenticatate.go @@ -2,6 +2,7 @@ package handler import ( "context" + "database/sql" "net/http" "time" @@ -9,47 +10,45 @@ import ( "projectreshoot/pkg/config" "projectreshoot/pkg/contexts" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" - "projectreshoot/pkg/jwt" + + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" - "github.com/rs/zerolog" ) // Get the tokens from the request func getTokens( - config *config.Config, - ctx context.Context, - tx db.SafeTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, r *http.Request, ) (*jwt.AccessToken, *jwt.RefreshToken, error) { // get the existing tokens from the cookies atStr, rtStr := cookies.GetTokenStrings(r) - aT, err := jwt.ParseAccessToken(config, ctx, tx, atStr) + aT, err := tokenGen.ValidateAccess(tx, atStr) if err != nil { - return nil, nil, errors.Wrap(err, "jwt.ParseAccessToken") + return nil, nil, errors.Wrap(err, "tokenGen.ValidateAccess") } - rT, err := jwt.ParseRefreshToken(config, ctx, tx, rtStr) + rT, err := tokenGen.ValidateRefresh(tx, rtStr) if err != nil { - return nil, nil, errors.Wrap(err, "jwt.ParseRefreshToken") + return nil, nil, errors.Wrap(err, "tokenGen.ValidateRefresh") } return aT, rT, nil } // Revoke the given token pair func revokeTokenPair( - ctx context.Context, - tx *db.SafeWTX, + tx *sql.Tx, aT *jwt.AccessToken, rT *jwt.RefreshToken, ) error { - err := jwt.RevokeToken(ctx, tx, aT) + err := aT.Revoke(tx) if err != nil { - return errors.Wrap(err, "jwt.RevokeToken") + return errors.Wrap(err, "aT.Revoke") } - err = jwt.RevokeToken(ctx, tx, rT) + err = rT.Revoke(tx) if err != nil { - return errors.Wrap(err, "jwt.RevokeToken") + return errors.Wrap(err, "rT.Revoke") } return nil } @@ -57,12 +56,12 @@ func revokeTokenPair( // Issue new tokens for the user, invalidating the old ones func refreshTokens( config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, w http.ResponseWriter, r *http.Request, ) error { - aT, rT, err := getTokens(config, ctx, tx, r) + aT, rT, err := getTokens(tokenGen, tx, r) if err != nil { return errors.Wrap(err, "getTokens") } @@ -72,11 +71,11 @@ func refreshTokens( }[aT.TTL] // issue new tokens for the user user := contexts.GetUser(r.Context()) - err = cookies.SetTokenCookies(w, r, config, user.User, true, rememberMe) + err = cookies.SetTokenCookies(w, r, config, tokenGen, user.User, true, rememberMe) if err != nil { return errors.Wrap(err, "cookies.SetTokenCookies") } - err = revokeTokenPair(ctx, tx, aT, rT) + err = revokeTokenPair(tx, aT, rT) if err != nil { return errors.Wrap(err, "revokeTokenPair") } @@ -86,12 +85,13 @@ func refreshTokens( // Validate the provided password func validatePassword( + tx *sql.Tx, r *http.Request, ) error { r.ParseForm() password := r.FormValue("password") user := contexts.GetUser(r.Context()) - err := user.CheckPassword(password) + err := user.CheckPassword(tx, password) if err != nil { return errors.Wrap(err, "user.CheckPassword") } @@ -100,9 +100,10 @@ func validatePassword( // Handle request to reauthenticate (i.e. make token fresh again) func Reauthenticate( - logger *zerolog.Logger, + logger *hlog.Logger, config *config.Config, - conn *db.SafeConn, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -110,22 +111,21 @@ func Reauthenticate( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { - logger.Warn().Err(err).Msg("Failed to refresh user tokens") - w.WriteHeader(http.StatusServiceUnavailable) + logger.Error().Err(err).Msg("Failed to start transaction") + w.WriteHeader(http.StatusInternalServerError) return } - err = validatePassword(r) + defer tx.Rollback() + err = validatePassword(tx, r) if err != nil { - tx.Rollback() w.WriteHeader(445) form.ConfirmPassword("Incorrect password").Render(r.Context(), w) return } - err = refreshTokens(config, ctx, tx, w, r) + err = refreshTokens(config, tokenGen, tx, w, r) if err != nil { - tx.Rollback() logger.Error().Err(err).Msg("Failed to refresh user tokens") w.WriteHeader(http.StatusInternalServerError) return diff --git a/internal/handler/register.go b/internal/handler/register.go index 226b3b7..5202667 100644 --- a/internal/handler/register.go +++ b/internal/handler/register.go @@ -2,6 +2,7 @@ package handler import ( "context" + "database/sql" "net/http" "time" @@ -10,23 +11,23 @@ import ( "projectreshoot/internal/view/page" "projectreshoot/pkg/config" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" + + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" - "github.com/rs/zerolog" ) func validateRegistration( - ctx context.Context, - tx *db.SafeWTX, + tx *sql.Tx, r *http.Request, ) (*models.User, error) { formUsername := r.FormValue("username") formPassword := r.FormValue("password") formConfirmPassword := r.FormValue("confirm-password") - unique, err := models.CheckUsernameUnique(ctx, tx, formUsername) + unique, err := models.CheckUsernameUnique(tx, formUsername) if err != nil { - return nil, errors.Wrap(err, "db.CheckUsernameUnique") + return nil, errors.Wrap(err, "models.CheckUsernameUnique") } if !unique { return nil, errors.New("Username is taken") @@ -37,9 +38,9 @@ func validateRegistration( if len(formPassword) > 72 { return nil, errors.New("Password exceeds maximum length of 72 bytes") } - user, err := models.CreateNewUser(ctx, tx, formUsername, formPassword) + user, err := models.CreateNewUser(tx, formUsername, formPassword) if err != nil { - return nil, errors.Wrap(err, "db.CreateNewUser") + return nil, errors.Wrap(err, "models.CreateNewUser") } return user, nil @@ -47,8 +48,9 @@ func validateRegistration( func RegisterRequest( config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, + tokenGen *jwt.TokenGenerator, + logger *hlog.Logger, + conn *sql.DB, ) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { @@ -56,14 +58,14 @@ func RegisterRequest( defer cancel() // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { logger.Warn().Err(err).Msg("Failed to set token cookies") w.WriteHeader(http.StatusServiceUnavailable) return } r.ParseForm() - user, err := validateRegistration(ctx, tx, r) + user, err := validateRegistration(tx, r) if err != nil { tx.Rollback() if err.Error() != "Username is taken" && @@ -78,7 +80,7 @@ func RegisterRequest( } rememberMe := checkRememberMe(r) - err = cookies.SetTokenCookies(w, r, config, user, true, rememberMe) + err = cookies.SetTokenCookies(w, r, config, tokenGen, user, true, rememberMe) if err != nil { tx.Rollback() w.WriteHeader(http.StatusInternalServerError) diff --git a/internal/httpserver/routes.go b/internal/httpserver/routes.go index e31bc7a..e96c04b 100644 --- a/internal/httpserver/routes.go +++ b/internal/httpserver/routes.go @@ -1,23 +1,25 @@ package httpserver import ( + "database/sql" "net/http" "projectreshoot/internal/handler" "projectreshoot/internal/middleware" "projectreshoot/internal/view/page" "projectreshoot/pkg/config" - "projectreshoot/pkg/db" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" ) // Add all the handled routes to the mux func addRoutes( mux *http.ServeMux, - logger *zerolog.Logger, + logger *hlog.Logger, config *config.Config, - conn *db.SafeConn, + tokenGen *jwt.TokenGenerator, + conn *sql.DB, staticFS *http.FileSystem, ) { route := mux.Handle @@ -39,17 +41,17 @@ func addRoutes( // Login page and handlers route("GET /login", loggedOut(handler.LoginPage(config.TrustedHost))) - route("POST /login", loggedOut(handler.LoginRequest(config, logger, conn))) + route("POST /login", loggedOut(handler.LoginRequest(config, logger, conn, tokenGen))) // Register page and handlers route("GET /register", loggedOut(handler.RegisterPage(config.TrustedHost))) - route("POST /register", loggedOut(handler.RegisterRequest(config, logger, conn))) + route("POST /register", loggedOut(handler.RegisterRequest(config, tokenGen, logger, conn))) // Logout - route("POST /logout", handler.Logout(config, logger, conn)) + route("POST /logout", handler.Logout(conn, tokenGen, logger)) // Reauthentication request - route("POST /reauthenticate", loggedIn(handler.Reauthenticate(logger, config, conn))) + route("POST /reauthenticate", loggedIn(handler.Reauthenticate(logger, config, conn, tokenGen))) // Profile page route("GET /profile", loggedIn(handler.ProfilePage())) diff --git a/internal/httpserver/server.go b/internal/httpserver/server.go index f634505..5d73bc4 100644 --- a/internal/httpserver/server.go +++ b/internal/httpserver/server.go @@ -1,6 +1,7 @@ package httpserver import ( + "database/sql" "io/fs" "net" "net/http" @@ -8,20 +9,21 @@ import ( "projectreshoot/internal/middleware" "projectreshoot/pkg/config" - "projectreshoot/pkg/db" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" ) func NewServer( config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, staticFS *fs.FS, maint *uint32, ) *http.Server { fs := http.FS(*staticFS) - srv := createServer(config, logger, conn, &fs, maint) + srv := createServer(config, logger, conn, tokenGen, &fs, maint) httpServer := &http.Server{ Addr: net.JoinHostPort(config.Host, config.Port), Handler: srv, @@ -35,8 +37,9 @@ func NewServer( // Returns a new http.Handler with all the routes and middleware added func createServer( config *config.Config, - logger *zerolog.Logger, - conn *db.SafeConn, + logger *hlog.Logger, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, staticFS *http.FileSystem, maint *uint32, ) http.Handler { @@ -45,6 +48,7 @@ func createServer( mux, logger, config, + tokenGen, conn, staticFS, ) @@ -52,7 +56,7 @@ func createServer( // Add middleware here, must be added in reverse order of execution // i.e. First in list will get executed last during the request handling handler = middleware.Logging(logger, handler) - handler = middleware.Authentication(logger, config, conn, handler, maint) + handler = middleware.Authentication(logger, config, conn, tokenGen, handler, maint) // Gzip handler = middleware.Gzip(handler, config.GZIP) diff --git a/internal/middleware/authentication.go b/internal/middleware/authentication.go index 4393eff..302dd35 100644 --- a/internal/middleware/authentication.go +++ b/internal/middleware/authentication.go @@ -2,6 +2,7 @@ package middleware import ( "context" + "database/sql" "net/http" "sync/atomic" "time" @@ -11,25 +12,24 @@ import ( "projectreshoot/pkg/config" "projectreshoot/pkg/contexts" "projectreshoot/pkg/cookies" - "projectreshoot/pkg/db" - "projectreshoot/pkg/jwt" + "git.haelnorr.com/h/golib/hlog" + "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" - "github.com/rs/zerolog" ) // Attempt to use a valid refresh token to generate a new token pair func refreshAuthTokens( config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, w http.ResponseWriter, req *http.Request, ref *jwt.RefreshToken, ) (*models.User, error) { - user, err := ref.GetUser(ctx, tx) + user, err := models.GetUserFromID(tx, ref.SUB) if err != nil { - return nil, errors.Wrap(err, "ref.GetUser") + return nil, errors.Wrap(err, "models.GetUser") } rememberMe := map[string]bool{ @@ -38,14 +38,14 @@ func refreshAuthTokens( }[ref.TTL] // Set fresh to true because new tokens coming from refresh request - err = cookies.SetTokenCookies(w, req, config, user, false, rememberMe) + err = cookies.SetTokenCookies(w, req, config, tokenGen, user, false, rememberMe) if err != nil { return nil, errors.Wrap(err, "cookies.SetTokenCookies") } // New tokens sent, revoke the used refresh token - err = jwt.RevokeToken(ctx, tx, ref) + err = ref.Revoke(tx) if err != nil { - return nil, errors.Wrap(err, "jwt.RevokeToken") + return nil, errors.Wrap(err, "ref.Revoke") } // Return the authorized user return user, nil @@ -54,23 +54,26 @@ func refreshAuthTokens( // Check the cookies for token strings and attempt to authenticate them func getAuthenticatedUser( config *config.Config, - ctx context.Context, - tx *db.SafeWTX, + tokenGen *jwt.TokenGenerator, + tx *sql.Tx, w http.ResponseWriter, r *http.Request, ) (*contexts.AuthenticatedUser, error) { // Get token strings from cookies atStr, rtStr := cookies.GetTokenStrings(r) + if atStr == "" && rtStr == "" { + return nil, errors.New("No token strings provided") + } // Attempt to parse the access token - aT, err := jwt.ParseAccessToken(config, ctx, tx, atStr) + aT, err := tokenGen.ValidateAccess(tx, atStr) if err != nil { // Access token invalid, attempt to parse refresh token - rT, err := jwt.ParseRefreshToken(config, ctx, tx, rtStr) + rT, err := tokenGen.ValidateRefresh(tx, rtStr) if err != nil { - return nil, errors.Wrap(err, "jwt.ParseRefreshToken") + return nil, errors.Wrap(err, "tokenGen.ValidateRefresh") } // Refresh token valid, attempt to get a new token pair - user, err := refreshAuthTokens(config, ctx, tx, w, r, rT) + user, err := refreshAuthTokens(config, tokenGen, tx, w, r, rT) if err != nil { return nil, errors.Wrap(err, "refreshAuthTokens") } @@ -82,9 +85,9 @@ func getAuthenticatedUser( return &authUser, nil } // Access token valid - user, err := aT.GetUser(ctx, tx) + user, err := models.GetUserFromID(tx, aT.SUB) if err != nil { - return nil, errors.Wrap(err, "aT.GetUser") + return nil, errors.Wrap(err, "models.GetUser") } authUser := contexts.AuthenticatedUser{ User: user, @@ -96,9 +99,10 @@ func getAuthenticatedUser( // Attempt to authenticate the user and add their account details // to the request context func Authentication( - logger *zerolog.Logger, + logger *hlog.Logger, config *config.Config, - conn *db.SafeConn, + conn *sql.DB, + tokenGen *jwt.TokenGenerator, next http.Handler, maint *uint32, ) http.Handler { @@ -115,7 +119,7 @@ func Authentication( } // Start the transaction - tx, err := conn.Begin(ctx) + tx, err := conn.BeginTx(ctx, nil) if err != nil { // Failed to start transaction, skip auth logger.Warn().Err(err). @@ -123,7 +127,7 @@ func Authentication( handler.ErrorPage(http.StatusServiceUnavailable, w, r) return } - user, err := getAuthenticatedUser(config, ctx, tx, w, r) + user, err := getAuthenticatedUser(config, tokenGen, tx, w, r) if err != nil { tx.Rollback() // User auth failed, delete the cookies to avoid repeat requests diff --git a/internal/middleware/authentication_test.go b/internal/middleware/authentication_test.go deleted file mode 100644 index df68ad0..0000000 --- a/internal/middleware/authentication_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package middleware - -import ( - "io" - "net/http" - "net/http/httptest" - "strconv" - "sync/atomic" - "testing" - - "projectreshoot/pkg/contexts" - "projectreshoot/pkg/db" - "projectreshoot/pkg/tests" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestAuthenticationMiddleware(t *testing.T) { - cfg, err := tests.TestConfig() - require.NoError(t, err) - logger := tests.NilLogger() - ver, err := strconv.ParseInt(cfg.DBName, 10, 0) - require.NoError(t, err) - wconn, rconn, err := tests.SetupTestDB(ver) - require.NoError(t, err) - sconn := db.MakeSafe(wconn, rconn, logger) - defer sconn.Close() - - // Handler to check outcome of Authentication middleware - testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - user := contexts.GetUser(r.Context()) - if user == nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(strconv.Itoa(0))) - return - } else { - w.WriteHeader(http.StatusOK) - w.Write([]byte(strconv.Itoa(user.ID))) - } - }) - var maint uint32 - atomic.StoreUint32(&maint, 0) - // Add the middleware and create the server - authHandler := Authentication(logger, cfg, sconn, testHandler, &maint) - require.NoError(t, err) - server := httptest.NewServer(authHandler) - defer server.Close() - - tokens := getTokens() - - tests := []struct { - name string - id int - accessToken string - refreshToken string - expectedCode int - }{ - { - name: "Valid Access Token (Fresh)", - id: 1, - accessToken: tokens["accessFresh"], - refreshToken: "", - expectedCode: http.StatusOK, - }, - { - name: "Valid Access Token (Unfresh)", - id: 1, - accessToken: tokens["accessUnfresh"], - refreshToken: tokens["refreshExpired"], - expectedCode: http.StatusOK, - }, - { - name: "Valid Refresh Token (Triggers Refresh)", - id: 1, - accessToken: tokens["accessExpired"], - refreshToken: tokens["refreshValid"], - expectedCode: http.StatusOK, - }, - { - name: "Both tokens expired", - accessToken: tokens["accessExpired"], - refreshToken: tokens["refreshExpired"], - expectedCode: http.StatusUnauthorized, - }, - { - name: "Access token revoked", - accessToken: tokens["accessRevoked"], - refreshToken: "", - expectedCode: http.StatusUnauthorized, - }, - { - name: "Refresh token revoked", - accessToken: "", - refreshToken: tokens["refreshRevoked"], - expectedCode: http.StatusUnauthorized, - }, - { - name: "Invalid Tokens", - accessToken: tokens["invalid"], - refreshToken: tokens["invalid"], - expectedCode: http.StatusUnauthorized, - }, - { - name: "No Tokens", - accessToken: "", - refreshToken: "", - expectedCode: http.StatusUnauthorized, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - client := &http.Client{} - - req, _ := http.NewRequest(http.MethodGet, server.URL, nil) - - // Add cookies if provided - if tt.accessToken != "" { - req.AddCookie(&http.Cookie{Name: "access", Value: tt.accessToken}) - } - if tt.refreshToken != "" { - req.AddCookie(&http.Cookie{Name: "refresh", Value: tt.refreshToken}) - } - - resp, err := client.Do(req) - assert.NoError(t, err) - assert.Equal(t, tt.expectedCode, resp.StatusCode) - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - assert.Equal(t, strconv.Itoa(tt.id), string(body)) - }) - } -} - -// get the tokens to test with -func getTokens() map[string]string { - tokens := map[string]string{ - "accessFresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ4OTU2NzIyMTAsImZyZXNoIjo0ODk1NjcyMjEwLCJpYXQiOjE3Mzk2NzIyMTAsImlzcyI6IjEyNy4wLjAuMSIsImp0aSI6ImE4Njk2YWM4LTg3OWMtNDdkNC1iZWM2LTRlY2Y4MTRiZThiZiIsInNjb3BlIjoiYWNjZXNzIiwic3ViIjoxLCJ0dGwiOiJzZXNzaW9uIn0.6nAquDY0JBLPdaJ9q_sMpKj1ISG4Vt2U05J57aoPue8", - "accessUnfresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjMzMjk5Njc1NjcxLCJmcmVzaCI6MTczOTY3NTY3MSwiaWF0IjoxNzM5Njc1NjcxLCJpc3MiOiIxMjcuMC4wLjEiLCJqdGkiOiJjOGNhZmFjNy0yODkzLTQzNzMtOTI4ZS03MGUwODJkYmM2MGIiLCJzY29wZSI6ImFjY2VzcyIsInN1YiI6MSwidHRsIjoic2Vzc2lvbiJ9.plWQVFwHlhXUYI5utS7ny1JfXjJSFrigkq-PnTHD5VY", - "accessExpired": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzk2NzIyNDgsImZyZXNoIjoxNzM5NjcyMjQ4LCJpYXQiOjE3Mzk2NzIyNDgsImlzcyI6IjEyNy4wLjAuMSIsImp0aSI6IjgxYzA1YzBjLTJhOGItNGQ2MC04Yzc4LWY2ZTQxODYxZDFmNCIsInNjb3BlIjoiYWNjZXNzIiwic3ViIjoxLCJ0dGwiOiJzZXNzaW9uIn0.iI1f17kKTuFDEMEYltJRIwRYgYQ-_nF9Wsn0KR6x77Q", - "refreshValid": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ4OTU2NzE5MjIsImlhdCI6MTczOTY3MTkyMiwiaXNzIjoiMTI3LjAuMC4xIiwianRpIjoiZTUxMTY3ZWEtNDA3OS00ZTczLTkzZDQtNTgwZDMzODRjZDU4Iiwic2NvcGUiOiJyZWZyZXNoIiwic3ViIjoxLCJ0dGwiOiJzZXNzaW9uIn0.tvtqQ8Z4WrYWHHb0MaEPdsU2FT2KLRE1zHOv3ipoFyc", - "refreshExpired": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzk2NzIyNDgsImlhdCI6MTczOTY3MjI0OCwiaXNzIjoiMTI3LjAuMC4xIiwianRpIjoiZTg5YTc5MTYtZGEzYi00YmJhLWI3ZDMtOWI1N2ViNjRhMmU0Iiwic2NvcGUiOiJyZWZyZXNoIiwic3ViIjoxLCJ0dGwiOiJzZXNzaW9uIn0.rH_fytC7Duxo598xacu820pQKF9ELbG8674h_bK_c4I", - "accessRevoked": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ4OTU2NzE5MjIsImZyZXNoIjoxNzM5NjcxOTIyLCJpYXQiOjE3Mzk2NzE5MjIsImlzcyI6IjEyNy4wLjAuMSIsImp0aSI6IjBhNmIzMzhlLTkzMGEtNDNmZS04ZjcwLTFhNmRhZWQyNTZmYSIsInNjb3BlIjoiYWNjZXNzIiwic3ViIjoxLCJ0dGwiOiJzZXNzaW9uIn0.mZLuCp9amcm2_CqYvbHPlk86nfiuy_Or8TlntUCw4Qs", - "refreshRevoked": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjMzMjk5Njc1NjcxLCJpYXQiOjE3Mzk2NzU2NzEsImlzcyI6IjEyNy4wLjAuMSIsImp0aSI6ImI3ZmE1MWRjLTg1MzItNDJlMS04NzU2LTVkMjViZmIyMDAzYSIsInNjb3BlIjoicmVmcmVzaCIsInN1YiI6MSwidHRsIjoic2Vzc2lvbiJ9.5Q9yDZN5FubfCWHclUUZEkJPOUHcOEpVpgcUK-ameHo", - "invalid": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODUxNDA5ODQsImlhdCI6MTQ4NTEzNzM4NCwiaXNzIjoiYWNtZS5jb20iLCJzdWIiOiIyOWFjMGMxOC0wYjRhLTQyY2YtODJmYy0wM2Q1NzAzMThhMWQiLCJhcHBsaWNhdGlvbklkIjoiNzkxMDM3MzQtOTdhYi00ZDFhLWFmMzctZTAwNmQwNWQyOTUyIiwicm9sZXMiOltdfQ.Mp0Pcwsz5VECK11Kf2ZZNF_SMKu5CgBeLN9ZOP04kZo", - } - return tokens -} diff --git a/internal/middleware/logging.go b/internal/middleware/logging.go index e890152..82bbffd 100644 --- a/internal/middleware/logging.go +++ b/internal/middleware/logging.go @@ -6,7 +6,7 @@ import ( "projectreshoot/pkg/contexts" "time" - "github.com/rs/zerolog" + "git.haelnorr.com/h/golib/hlog" ) // Wraps the http.ResponseWriter, adding a statusCode field @@ -22,7 +22,7 @@ func (w *wrappedWriter) WriteHeader(statusCode int) { } // Middleware to add logs to console with details of the request -func Logging(logger *zerolog.Logger, next http.Handler) http.Handler { +func Logging(logger *hlog.Logger, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/static/css/output.css" || r.URL.Path == "/static/favicon.ico" { diff --git a/internal/middleware/pageprotection_test.go b/internal/middleware/pageprotection_test.go deleted file mode 100644 index 8cbc81b..0000000 --- a/internal/middleware/pageprotection_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "strconv" - "sync/atomic" - "testing" - - "projectreshoot/pkg/db" - "projectreshoot/pkg/tests" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestPageLoginRequired(t *testing.T) { - cfg, err := tests.TestConfig() - require.NoError(t, err) - logger := tests.NilLogger() - ver, err := strconv.ParseInt(cfg.DBName, 10, 0) - require.NoError(t, err) - wconn, rconn, err := tests.SetupTestDB(ver) - require.NoError(t, err) - sconn := db.MakeSafe(wconn, rconn, logger) - defer sconn.Close() - - // Handler to check outcome of Authentication middleware - testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }) - - var maint uint32 - atomic.StoreUint32(&maint, 0) - // Add the middleware and create the server - loginRequiredHandler := LoginReq(testHandler) - authHandler := Authentication(logger, cfg, sconn, loginRequiredHandler, &maint) - server := httptest.NewServer(authHandler) - defer server.Close() - - tokens := getTokens() - - tests := []struct { - name string - accessToken string - refreshToken string - expectedCode int - }{ - { - name: "Valid Login", - accessToken: tokens["accessFresh"], - refreshToken: "", - expectedCode: http.StatusOK, - }, - { - name: "Expired login", - accessToken: tokens["accessExpired"], - refreshToken: tokens["refreshExpired"], - expectedCode: http.StatusUnauthorized, - }, - { - name: "No login", - accessToken: "", - refreshToken: "", - expectedCode: http.StatusUnauthorized, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - client := &http.Client{} - - req, _ := http.NewRequest(http.MethodGet, server.URL, nil) - - // Add cookies if provided - if tt.accessToken != "" { - req.AddCookie(&http.Cookie{Name: "access", Value: tt.accessToken}) - } - if tt.refreshToken != "" { - req.AddCookie(&http.Cookie{Name: "refresh", Value: tt.refreshToken}) - } - - resp, err := client.Do(req) - assert.NoError(t, err) - assert.Equal(t, tt.expectedCode, resp.StatusCode) - }) - } -} diff --git a/internal/middleware/reauthentication_test.go b/internal/middleware/reauthentication_test.go deleted file mode 100644 index de407e0..0000000 --- a/internal/middleware/reauthentication_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "strconv" - "sync/atomic" - "testing" - - "projectreshoot/pkg/db" - "projectreshoot/pkg/tests" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestReauthRequired(t *testing.T) { - cfg, err := tests.TestConfig() - require.NoError(t, err) - logger := tests.NilLogger() - ver, err := strconv.ParseInt(cfg.DBName, 10, 0) - require.NoError(t, err) - wconn, rconn, err := tests.SetupTestDB(ver) - require.NoError(t, err) - sconn := db.MakeSafe(wconn, rconn, logger) - defer sconn.Close() - - // Handler to check outcome of Authentication middleware - testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }) - - var maint uint32 - atomic.StoreUint32(&maint, 0) - // Add the middleware and create the server - reauthRequiredHandler := FreshReq(testHandler) - loginRequiredHandler := LoginReq(reauthRequiredHandler) - authHandler := Authentication(logger, cfg, sconn, loginRequiredHandler, &maint) - server := httptest.NewServer(authHandler) - defer server.Close() - - tokens := getTokens() - - tests := []struct { - name string - accessToken string - refreshToken string - expectedCode int - }{ - { - name: "Fresh Login", - accessToken: tokens["accessFresh"], - refreshToken: "", - expectedCode: http.StatusOK, - }, - { - name: "Unfresh Login", - accessToken: tokens["accessUnfresh"], - refreshToken: "", - expectedCode: 444, - }, - { - name: "Expired login", - accessToken: tokens["accessExpired"], - refreshToken: tokens["refreshExpired"], - expectedCode: http.StatusUnauthorized, - }, - { - name: "No login", - accessToken: "", - refreshToken: "", - expectedCode: http.StatusUnauthorized, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - client := &http.Client{} - - req, _ := http.NewRequest(http.MethodGet, server.URL, nil) - - // Add cookies if provided - if tt.accessToken != "" { - req.AddCookie(&http.Cookie{Name: "access", Value: tt.accessToken}) - } - if tt.refreshToken != "" { - req.AddCookie(&http.Cookie{Name: "refresh", Value: tt.refreshToken}) - } - - resp, err := client.Do(req) - assert.NoError(t, err) - assert.Equal(t, tt.expectedCode, resp.StatusCode) - }) - } -} diff --git a/internal/models/user.go b/internal/models/user.go index 47a2341..3f93ea2 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -1,30 +1,31 @@ package models import ( - "context" - "projectreshoot/pkg/db" + "database/sql" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" ) type User struct { - ID int // Integer ID (index primary key) - Username string // Username (unique) - Password_hash string // Bcrypt password hash - Created_at int64 // Epoch timestamp when the user was added to the database - Bio string // Short byline set by the user + ID int // Integer ID (index primary key) + Username string // Username (unique) + Created_at int64 // Epoch timestamp when the user was added to the database + Bio string // Short byline set by the user } // Uses bcrypt to set the users Password_hash from the given password -func (user *User) SetPassword(ctx context.Context, tx *db.SafeWTX, password string) error { +func (user *User) SetPassword( + tx *sql.Tx, + password string, +) error { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return errors.Wrap(err, "bcrypt.GenerateFromPassword") } - user.Password_hash = string(hashedPassword) + newPassword := string(hashedPassword) query := `UPDATE users SET password_hash = ? WHERE id = ?` - _, err = tx.Exec(ctx, query, user.Password_hash, user.ID) + _, err = tx.Exec(query, newPassword, user.ID) if err != nil { return errors.Wrap(err, "tx.Exec") } @@ -32,8 +33,15 @@ func (user *User) SetPassword(ctx context.Context, tx *db.SafeWTX, password stri } // Uses bcrypt to check if the given password matches the users Password_hash -func (user *User) CheckPassword(password string) error { - err := bcrypt.CompareHashAndPassword([]byte(user.Password_hash), []byte(password)) +func (user *User) CheckPassword(tx *sql.Tx, password string) error { + query := `SELECT password_hash FROM users WHERE id = ? LIMIT 1` + row := tx.QueryRow(query, user.ID) + hashedPassword := "" + err := row.Scan(&hashedPassword) + if err != nil { + return errors.Wrap(err, "row.Scan") + } + err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) if err != nil { return errors.Wrap(err, "bcrypt.CompareHashAndPassword") } @@ -41,9 +49,9 @@ func (user *User) CheckPassword(password string) error { } // Change the user's username -func (user *User) ChangeUsername(ctx context.Context, tx *db.SafeWTX, newUsername string) error { +func (user *User) ChangeUsername(tx *sql.Tx, newUsername string) error { query := `UPDATE users SET username = ? WHERE id = ?` - _, err := tx.Exec(ctx, query, newUsername, user.ID) + _, err := tx.Exec(query, newUsername, user.ID) if err != nil { return errors.Wrap(err, "tx.Exec") } @@ -51,9 +59,9 @@ func (user *User) ChangeUsername(ctx context.Context, tx *db.SafeWTX, newUsernam } // Change the user's bio -func (user *User) ChangeBio(ctx context.Context, tx *db.SafeWTX, newBio string) error { +func (user *User) ChangeBio(tx *sql.Tx, newBio string) error { query := `UPDATE users SET bio = ? WHERE id = ?` - _, err := tx.Exec(ctx, query, newBio, user.ID) + _, err := tx.Exec(query, newBio, user.ID) if err != nil { return errors.Wrap(err, "tx.Exec") } diff --git a/internal/models/user_functions.go b/internal/models/user_functions.go index 2bfea8a..da4e5e0 100644 --- a/internal/models/user_functions.go +++ b/internal/models/user_functions.go @@ -1,31 +1,28 @@ package models import ( - "context" "database/sql" "fmt" - "projectreshoot/pkg/db" "github.com/pkg/errors" ) // Creates a new user in the database and returns a pointer func CreateNewUser( - ctx context.Context, - tx *db.SafeWTX, + tx *sql.Tx, username string, password string, ) (*User, error) { query := `INSERT INTO users (username) VALUES (?)` - _, err := tx.Exec(ctx, query, username) + _, err := tx.Exec(query, username) if err != nil { return nil, errors.Wrap(err, "tx.Exec") } - user, err := GetUserFromUsername(ctx, tx, username) + user, err := GetUserFromUsername(tx, username) if err != nil { return nil, errors.Wrap(err, "GetUserFromUsername") } - err = user.SetPassword(ctx, tx, password) + err = user.SetPassword(tx, password) if err != nil { return nil, errors.Wrap(err, "user.SetPassword") } @@ -34,23 +31,21 @@ func CreateNewUser( // Fetches data from the users table using "WHERE column = 'value'" func fetchUserData( - ctx context.Context, - tx db.SafeTX, + tx *sql.Tx, column string, - value interface{}, + value any, ) (*sql.Rows, error) { query := fmt.Sprintf( `SELECT id, username, - password_hash, created_at, bio FROM users WHERE %s = ? COLLATE NOCASE LIMIT 1`, column, ) - rows, err := tx.Query(ctx, query, value) + rows, err := tx.Query(query, value) if err != nil { return nil, errors.Wrap(err, "tx.Query") } @@ -66,7 +61,6 @@ func scanUserRow(user *User, rows *sql.Rows) error { err := rows.Scan( &user.ID, &user.Username, - &user.Password_hash, &user.Created_at, &user.Bio, ) @@ -78,8 +72,8 @@ func scanUserRow(user *User, rows *sql.Rows) error { // Queries the database for a user matching the given username. // Query is case insensitive -func GetUserFromUsername(ctx context.Context, tx db.SafeTX, username string) (*User, error) { - rows, err := fetchUserData(ctx, tx, "username", username) +func GetUserFromUsername(tx *sql.Tx, username string) (*User, error) { + rows, err := fetchUserData(tx, "username", username) if err != nil { return nil, errors.Wrap(err, "fetchUserData") } @@ -93,8 +87,8 @@ func GetUserFromUsername(ctx context.Context, tx db.SafeTX, username string) (*U } // Queries the database for a user matching the given ID. -func GetUserFromID(ctx context.Context, tx db.SafeTX, id int) (*User, error) { - rows, err := fetchUserData(ctx, tx, "id", id) +func GetUserFromID(tx *sql.Tx, id int) (*User, error) { + rows, err := fetchUserData(tx, "id", id) if err != nil { return nil, errors.Wrap(err, "fetchUserData") } @@ -108,9 +102,9 @@ func GetUserFromID(ctx context.Context, tx db.SafeTX, id int) (*User, error) { } // Checks if the given username is unique. Returns true if not taken -func CheckUsernameUnique(ctx context.Context, tx db.SafeTX, username string) (bool, error) { +func CheckUsernameUnique(tx *sql.Tx, username string) (bool, error) { query := `SELECT 1 FROM users WHERE username = ? COLLATE NOCASE LIMIT 1` - rows, err := tx.Query(ctx, query, username) + rows, err := tx.Query(query, username) if err != nil { return false, errors.Wrap(err, "tx.Query") } diff --git a/internal/view/component/account/changebio_templ.go b/internal/view/component/account/changebio_templ.go deleted file mode 100644 index 935782e..0000000 --- a/internal/view/component/account/changebio_templ.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/pkg/contexts" - -func ChangeBio(err string, bio string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - - user := contexts.GetUser(ctx) - if bio == "" { - bio = user.Bio - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/changepassword_templ.go b/internal/view/component/account/changepassword_templ.go deleted file mode 100644 index 4808626..0000000 --- a/internal/view/component/account/changepassword_templ.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func ChangePassword(err string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/changeusername_templ.go b/internal/view/component/account/changeusername_templ.go deleted file mode 100644 index 22f647b..0000000 --- a/internal/view/component/account/changeusername_templ.go +++ /dev/null @@ -1,62 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/pkg/contexts" - -func ChangeUsername(err string, username string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - - user := contexts.GetUser(ctx) - if username == "" { - username = user.Username - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/container_templ.go b/internal/view/component/account/container_templ.go deleted file mode 100644 index 5cb89da..0000000 --- a/internal/view/component/account/container_templ.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func AccountContainer(subpage string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = SelectMenu(subpage).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(subpage) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/account/container.templ`, Line: 16, Col: 13} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - switch subpage { - case "General": - templ_7745c5c3_Err = AccountGeneral().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - case "Security": - templ_7745c5c3_Err = AccountSecurity().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/general_templ.go b/internal/view/component/account/general_templ.go deleted file mode 100644 index 39d9a7a..0000000 --- a/internal/view/component/account/general_templ.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func AccountGeneral() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = ChangeUsername("", "").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = ChangeBio("", "").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/security_templ.go b/internal/view/component/account/security_templ.go deleted file mode 100644 index a0b15e5..0000000 --- a/internal/view/component/account/security_templ.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func AccountSecurity() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = ChangePassword("").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/account/selectmenu_templ.go b/internal/view/component/account/selectmenu_templ.go deleted file mode 100644 index 86021b5..0000000 --- a/internal/view/component/account/selectmenu_templ.go +++ /dev/null @@ -1,131 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package account - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "fmt" - -type MenuItem struct { - name string - href string -} - -func getMenuItems() []MenuItem { - return []MenuItem{ - { - name: "General", - href: "general", - }, - { - name: "Security", - href: "security", - }, - { - name: "Preferences", - href: "preferences", - }, - } -} - -func SelectMenu(activePage string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - - menuItems := getMenuItems() - page := fmt.Sprintf("{page:'%s'}", activePage) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - for _, item := range menuItems { - - activebind := fmt.Sprintf("page === '%s' && 'bg-mantle'", item.name) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
  • ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/footer/footer_templ.go b/internal/view/component/footer/footer_templ.go deleted file mode 100644 index 359e1ff..0000000 --- a/internal/view/component/footer/footer_templ.go +++ /dev/null @@ -1,92 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package footer - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -type FooterItem struct { - name string - href string -} - -// Specify the links to show in the footer -func getFooterItems() []FooterItem { - return []FooterItem{ - { - name: "About", - href: "/about", - }, - { - name: "Github", - href: "https://github.com/haelnorr/projectreshoot", - }, - } -} - -// Returns the template fragment for the Footer -func Footer() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/form/confirmpass_templ.go b/internal/view/component/form/confirmpass_templ.go deleted file mode 100644 index ceed0b2..0000000 --- a/internal/view/component/form/confirmpass_templ.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package form - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func ConfirmPassword(err string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/form/loginform_templ.go b/internal/view/component/form/loginform_templ.go deleted file mode 100644 index e8bc085..0000000 --- a/internal/view/component/form/loginform_templ.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package form - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// Login Form. If loginError is not an empty string, it will display the -// contents of loginError to the user. -// If loginError is "Username or password incorrect" it will also show -// error icons on the username and password field -func LoginForm(loginError string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - credErr := "Username or password incorrect" - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/form/registerform_templ.go b/internal/view/component/form/registerform_templ.go deleted file mode 100644 index d332b3f..0000000 --- a/internal/view/component/form/registerform_templ.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package form - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// Login Form. If loginError is not an empty string, it will display the -// contents of loginError to the user. -func RegisterForm(registerError string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - - usernameErr := "Username is taken" - passErrs := []string{ - "Password exceeds maximum length of 72 bytes", - "Passwords do not match", - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/nav/navbar_templ.go b/internal/view/component/nav/navbar_templ.go deleted file mode 100644 index 7e7b2f8..0000000 --- a/internal/view/component/nav/navbar_templ.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package nav - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -type NavItem struct { - name string // Label to display - href string // Link reference -} - -// Return the list of navbar links -func getNavItems() []NavItem { - return []NavItem{ - { - name: "Movies", - href: "/movies", - }, - } -} - -// Returns the navbar template fragment -func Navbar() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - navItems := getNavItems() - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Project Reshoot
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = navLeft(navItems).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = navRight().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = sideNav(navItems).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/nav/navbarleft_templ.go b/internal/view/component/nav/navbarleft_templ.go deleted file mode 100644 index 119bb65..0000000 --- a/internal/view/component/nav/navbarleft_templ.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package nav - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -// Returns the left portion of the navbar -func navLeft(navItems []NavItem) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/nav/navbarright_templ.go b/internal/view/component/nav/navbarright_templ.go deleted file mode 100644 index 98515bc..0000000 --- a/internal/view/component/nav/navbarright_templ.go +++ /dev/null @@ -1,124 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package nav - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/pkg/contexts" - -type ProfileItem struct { - name string // Label to display - href string // Link reference -} - -// Return the list of profile links -func getProfileItems() []ProfileItem { - return []ProfileItem{ - { - name: "Profile", - href: "/profile", - }, - { - name: "Account", - href: "/account", - }, - } -} - -// Returns the right portion of the navbar -func navRight() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - user := contexts.GetUser(ctx) - items := getProfileItems() - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if user != nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "Login Register") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/nav/sidenav_templ.go b/internal/view/component/nav/sidenav_templ.go deleted file mode 100644 index 3fb57d6..0000000 --- a/internal/view/component/nav/sidenav_templ.go +++ /dev/null @@ -1,86 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package nav - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/pkg/contexts" - -// Returns the mobile version of the navbar thats only visible when activated -func sideNav(navItems []NavItem) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - user := contexts.GetUser(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if user == nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/popup/confirmPasswordModal_templ.go b/internal/view/component/popup/confirmPasswordModal_templ.go deleted file mode 100644 index eaee3cd..0000000 --- a/internal/view/component/popup/confirmPasswordModal_templ.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 - -package popup - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/component/form" - -func ConfirmPasswordModal() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
To complete this action you need to confirm your password
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = form.ConfirmPassword("").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/popup/error500Popup_templ.go b/internal/view/component/popup/error500Popup_templ.go deleted file mode 100644 index cd21eef..0000000 --- a/internal/view/component/popup/error500Popup_templ.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package popup - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func Error500Popup() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Something went wrong

An error occured on the server. Please try again later, or contact an administrator

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/popup/error503Popup_templ.go b/internal/view/component/popup/error503Popup_templ.go deleted file mode 100644 index e542023..0000000 --- a/internal/view/component/popup/error503Popup_templ.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package popup - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -func Error503Popup() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Service Unavailable

The service is currently available. It could be down for maintenance. Please try again later.

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/component/search/movies_results.templ b/internal/view/component/search/movies_results.templ index d8d8e7a..3dce75c 100644 --- a/internal/view/component/search/movies_results.templ +++ b/internal/view/component/search/movies_results.templ @@ -1,7 +1,7 @@ package search -import "projectreshoot/pkg/tmdb" import "fmt" +import "git.haelnorr.com/h/golib/tmdb" templ MovieResults(movies *tmdb.ResultMovies, image *tmdb.Image) { for _, movie := range movies.Results { @@ -18,23 +18,23 @@ templ MovieResults(movies *tmdb.ResultMovies, image *tmdb.Image) { onerror="this.onerror=null; setFallbackColor(this);" /> + function setFallbackColor(img) { + const baseColor = getComputedStyle(document.documentElement). + getPropertyValue('--base').trim(); + img.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='144'%3E%3Crect width='100%' height='100%' fill='${baseColor}'/%3E%3C/svg%3E`; + } +
{ movie.Title } { movie.ReleaseYear() }

- Released: + Released: { movie.ReleaseDate }

- Original Title: + Original Title: { movie.OriginalTitle }

{ movie.Overview }

diff --git a/internal/view/component/search/movies_results_templ.go b/internal/view/component/search/movies_results_templ.go deleted file mode 100644 index 70ca412..0000000 --- a/internal/view/component/search/movies_results_templ.go +++ /dev/null @@ -1,132 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package search - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/pkg/tmdb" -import "fmt" - -func MovieResults(movies *tmdb.ResultMovies, image *tmdb.Image) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - for _, movie := range movies.Results { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
\"Movie
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(movie.Title) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/search/movies_results.templ`, Line: 31, Col: 18} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(movie.ReleaseYear()) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/search/movies_results.templ`, Line: 31, Col: 42} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

Released: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(movie.ReleaseDate) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/search/movies_results.templ`, Line: 34, Col: 50} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "

Original Title: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(movie.OriginalTitle) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/search/movies_results.templ`, Line: 38, Col: 52} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(movie.Overview) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/component/search/movies_results.templ`, Line: 40, Col: 45} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/layout/global_templ.go b/internal/view/layout/global_templ.go deleted file mode 100644 index cfca892..0000000 --- a/internal/view/layout/global_templ.go +++ /dev/null @@ -1,99 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package layout - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/component/nav" -import "projectreshoot/internal/view/component/footer" -import "projectreshoot/internal/view/component/popup" - -// Global page layout. Includes HTML document settings, header tags -// navbar and footer -func Global(title string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/layout/global.templ`, Line: 36, Col: 17} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = popup.Error500Popup().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = popup.Error503Popup().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = popup.ConfirmPasswordModal().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = nav.Navbar().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = footer.Footer().Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/about_templ.go b/internal/view/page/about_templ.go deleted file mode 100644 index f449951..0000000 --- a/internal/view/page/about_templ.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package page - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/layout" - -// Returns the about page content -func About() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
About
What is Project Reshoot?
Project Reshoot is a movie review site that aims to provide a better experience for the users. Instead of a single number that shows the average, or a spread of star ratings, Project Reshoot asks you to rate movies with a vibe. These ratings are shown as an easy to see pie chart showing how everyone felt.
The other major feature is the ability for you to customize what details you see about movies, hiding details you don't want to see until after you've watched it. This gives you peace of mind when searching for new movies to watch.
Why the name?
The name came partially from the premise of wanting to deliver a new take on movie reviews, and partially from it being rewritten from scratch in a new technology stack (Goodbye NextJS, Hello GOTH).
Who's behind it?
Currently Project Reshoot is being built by a team of 1. It is somewhat of a passion project and a way to practice my development skills. For the time being, it will likely stay that way, but if you want to contribute, you can check out the Github repo here.
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) - templ_7745c5c3_Err = layout.Global("About").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/account_templ.go b/internal/view/page/account_templ.go deleted file mode 100644 index 3f8c7fa..0000000 --- a/internal/view/page/account_templ.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package page - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/layout" -import "projectreshoot/internal/view/component/account" - -func Account(subpage string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = account.AccountContainer(subpage).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) - templ_7745c5c3_Err = layout.Global("Account - "+subpage).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/error_templ.go b/internal/view/page/error_templ.go deleted file mode 100644 index 9a3f240..0000000 --- a/internal/view/page/error_templ.go +++ /dev/null @@ -1,103 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package page - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/layout" -import "strconv" - -// Page template for Error pages. Error code should be a HTTP status code as -// a string, and err should be the corresponding response title. -// Message is a custom error message displayed below the code and error. -func Error(code int, err string, message string) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(code)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/page/error.templ`, Line: 18, Col: 25} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(err) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/page/error.templ`, Line: 22, Col: 10} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(message) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/view/page/error.templ`, Line: 25, Col: 14} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Go to homepage
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) - templ_7745c5c3_Err = layout.Global(err).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/index_templ.go b/internal/view/page/index_templ.go deleted file mode 100644 index 1e53b57..0000000 --- a/internal/view/page/index_templ.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package page - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/layout" - -// Page content for the index page -func Index() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
Project Reshoot
A better way to discover and rate films
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) - templ_7745c5c3_Err = layout.Global("Project Reshoot").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/login_templ.go b/internal/view/page/login_templ.go deleted file mode 100644 index 923ea97..0000000 --- a/internal/view/page/login_templ.go +++ /dev/null @@ -1,70 +0,0 @@ -// Code generated by templ - DO NOT EDIT. - -// templ: version: v0.3.833 -package page - -//lint:file-ignore SA4006 This context is only used if a nested component is present. - -import "github.com/a-h/templ" -import templruntime "github.com/a-h/templ/runtime" - -import "projectreshoot/internal/view/layout" -import "projectreshoot/internal/view/component/form" - -// Returns the login page -func Login() templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var1 := templ.GetChildren(ctx) - if templ_7745c5c3_Var1 == nil { - templ_7745c5c3_Var1 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

Login

Don't have an account yet? Sign up here

Or
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = form.LoginForm("").Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) - templ_7745c5c3_Err = layout.Global("Login").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - -var _ = templruntime.GeneratedTemplate diff --git a/internal/view/page/movie.templ b/internal/view/page/movie.templ index 3bc38ae..3851d1e 100644 --- a/internal/view/page/movie.templ +++ b/internal/view/page/movie.templ @@ -1,15 +1,12 @@ package page -import "projectreshoot/pkg/tmdb" +import "git.haelnorr.com/h/golib/tmdb" import "projectreshoot/internal/view/layout" templ Movie(movie *tmdb.Movie, credits *tmdb.Credits, image *tmdb.Image) { @layout.Global(movie.Title) {
-