modularised webserver and auth systems
This commit is contained in:
52
cmd/projectreshoot/auth.go
Normal file
52
cmd/projectreshoot/auth.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"projectreshoot/internal/config"
|
||||
"projectreshoot/internal/handler"
|
||||
"projectreshoot/internal/models"
|
||||
"projectreshoot/pkg/contexts"
|
||||
|
||||
"git.haelnorr.com/h/golib/hlog"
|
||||
"git.haelnorr.com/h/golib/hws"
|
||||
"git.haelnorr.com/h/golib/hwsauth"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func setupAuth(
|
||||
config *config.Config,
|
||||
logger *hlog.Logger,
|
||||
conn *sql.DB,
|
||||
server *hws.Server,
|
||||
ignoredPaths []string,
|
||||
) (*hwsauth.Authenticator[*models.User], error) {
|
||||
auth, err := hwsauth.NewAuthenticator(
|
||||
models.GetUserFromID,
|
||||
server,
|
||||
conn,
|
||||
logger,
|
||||
handler.NewErrorPage,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "hwsauth.NewAuthenticator")
|
||||
}
|
||||
|
||||
auth.SSL = config.SSL
|
||||
auth.AccessTokenExpiry = config.AccessTokenExpiry
|
||||
auth.RefreshTokenExpiry = config.RefreshTokenExpiry
|
||||
auth.TokenFreshTime = config.TokenFreshTime
|
||||
auth.TrustedHost = config.TrustedHost
|
||||
auth.SecretKey = config.SecretKey
|
||||
auth.LandingPage = "/profile"
|
||||
|
||||
auth.IgnorePaths(ignoredPaths...)
|
||||
|
||||
err = auth.Initialise()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "auth.Initialise")
|
||||
}
|
||||
|
||||
contexts.CurrentUser = auth.CurrentModel
|
||||
|
||||
return auth, nil
|
||||
}
|
||||
69
cmd/projectreshoot/httpserver.go
Normal file
69
cmd/projectreshoot/httpserver.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"git.haelnorr.com/h/golib/hws"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"projectreshoot/internal/config"
|
||||
|
||||
"git.haelnorr.com/h/golib/hlog"
|
||||
"git.haelnorr.com/h/golib/jwt"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func setupHttpServer(
|
||||
staticFS *fs.FS,
|
||||
config *config.Config,
|
||||
logger *hlog.Logger,
|
||||
conn *sql.DB,
|
||||
tokenGen *jwt.TokenGenerator,
|
||||
) (server *hws.Server, err error) {
|
||||
if staticFS == nil {
|
||||
return nil, errors.New("No filesystem provided")
|
||||
}
|
||||
fs := http.FS(*staticFS)
|
||||
httpServer, err := hws.NewServer(
|
||||
config.Host,
|
||||
config.Port,
|
||||
config.ReadHeaderTimeout,
|
||||
config.WriteTimeout,
|
||||
config.IdleTimeout,
|
||||
config.GZIP,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "hws.NewServer")
|
||||
}
|
||||
|
||||
ignoredPaths := []string{
|
||||
"/static/css/output.css",
|
||||
"/static/favicon.ico",
|
||||
}
|
||||
|
||||
auth, err := setupAuth(config, logger, conn, httpServer, ignoredPaths)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "setupAuth")
|
||||
}
|
||||
|
||||
err = httpServer.AddLogger(logger)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "httpServer.AddLogger")
|
||||
}
|
||||
|
||||
err = httpServer.LoggerIgnorePaths(ignoredPaths...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "httpServer.LoggerIgnorePaths")
|
||||
}
|
||||
|
||||
err = addRoutes(httpServer, &fs, config, logger, conn, tokenGen, auth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "addRoutes")
|
||||
}
|
||||
|
||||
err = addMiddleware(httpServer, auth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "httpServer.AddMiddleware")
|
||||
}
|
||||
|
||||
return httpServer, nil
|
||||
}
|
||||
23
cmd/projectreshoot/middleware.go
Normal file
23
cmd/projectreshoot/middleware.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.haelnorr.com/h/golib/hws"
|
||||
"git.haelnorr.com/h/golib/hwsauth"
|
||||
"projectreshoot/internal/models"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func addMiddleware(
|
||||
server *hws.Server,
|
||||
auth *hwsauth.Authenticator[*models.User],
|
||||
) error {
|
||||
|
||||
err := server.AddMiddleware(
|
||||
auth.Authenticate(),
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "server.AddMiddleware")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
127
cmd/projectreshoot/routes.go
Normal file
127
cmd/projectreshoot/routes.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"git.haelnorr.com/h/golib/hws"
|
||||
"git.haelnorr.com/h/golib/hwsauth"
|
||||
"net/http"
|
||||
"projectreshoot/internal/config"
|
||||
"projectreshoot/internal/handler"
|
||||
"projectreshoot/internal/models"
|
||||
"projectreshoot/internal/view/page"
|
||||
|
||||
"git.haelnorr.com/h/golib/hlog"
|
||||
"git.haelnorr.com/h/golib/jwt"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func addRoutes(
|
||||
server *hws.Server,
|
||||
staticFS *http.FileSystem,
|
||||
config *config.Config,
|
||||
logger *hlog.Logger,
|
||||
conn *sql.DB,
|
||||
tokenGen *jwt.TokenGenerator,
|
||||
auth *hwsauth.Authenticator[*models.User],
|
||||
) error {
|
||||
// Create the routes
|
||||
routes := []hws.Route{
|
||||
{
|
||||
Path: "/static/",
|
||||
Method: hws.MethodGET,
|
||||
Handler: http.StripPrefix("/static/", handler.StaticFS(staticFS, logger)),
|
||||
},
|
||||
{
|
||||
Path: "/",
|
||||
Method: hws.MethodGET,
|
||||
Handler: handler.Root(),
|
||||
},
|
||||
{
|
||||
Path: "/about",
|
||||
Method: hws.MethodGET,
|
||||
Handler: handler.HandlePage(page.About()),
|
||||
},
|
||||
{
|
||||
Path: "/login",
|
||||
Method: hws.MethodGET,
|
||||
Handler: auth.LogoutReq(handler.LoginPage(config.TrustedHost)),
|
||||
},
|
||||
{
|
||||
Path: "/login",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LogoutReq(handler.LoginRequest(server, auth, conn)),
|
||||
},
|
||||
{
|
||||
Path: "/register",
|
||||
Method: hws.MethodGET,
|
||||
Handler: auth.LogoutReq(handler.RegisterPage(config.TrustedHost)),
|
||||
},
|
||||
{
|
||||
Path: "/register",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LogoutReq(handler.RegisterRequest(config, logger, conn, tokenGen)),
|
||||
},
|
||||
{
|
||||
Path: "/logout",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: handler.Logout(server, auth, conn),
|
||||
},
|
||||
{
|
||||
Path: "/reauthenticate",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LoginReq(handler.Reauthenticate(server, auth, conn)),
|
||||
},
|
||||
{
|
||||
Path: "/profile",
|
||||
Method: hws.MethodGET,
|
||||
Handler: auth.LoginReq(handler.ProfilePage()),
|
||||
},
|
||||
{
|
||||
Path: "/account",
|
||||
Method: hws.MethodGET,
|
||||
Handler: auth.LoginReq(handler.AccountPage()),
|
||||
},
|
||||
{
|
||||
Path: "/account-select-page",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LoginReq(handler.AccountSubpage()),
|
||||
},
|
||||
{
|
||||
Path: "/change-username",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LoginReq(auth.FreshReq(handler.ChangeUsername(server, auth, conn))),
|
||||
},
|
||||
{
|
||||
Path: "/change-password",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LoginReq(auth.FreshReq(handler.ChangePassword(server, auth, conn))),
|
||||
},
|
||||
{
|
||||
Path: "/change-bio",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: auth.LoginReq(handler.ChangeBio(server, auth, conn)),
|
||||
},
|
||||
{
|
||||
Path: "/movies",
|
||||
Method: hws.MethodGET,
|
||||
Handler: handler.MoviesPage(),
|
||||
},
|
||||
{
|
||||
Path: "/search-movies",
|
||||
Method: hws.MethodPOST,
|
||||
Handler: handler.SearchMovies(config, logger),
|
||||
},
|
||||
{
|
||||
Path: "/movie/{movie_id}",
|
||||
Method: hws.MethodGET,
|
||||
Handler: handler.Movie(config, logger),
|
||||
},
|
||||
}
|
||||
|
||||
// Register the routes with the server
|
||||
err := server.AddRoutes(routes...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "server.AddRoutes")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -4,11 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"projectreshoot/internal/config"
|
||||
"projectreshoot/internal/httpserver"
|
||||
"projectreshoot/pkg/embedfs"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -62,16 +60,17 @@ func run(ctx context.Context, w io.Writer, args map[string]string, config *confi
|
||||
)
|
||||
|
||||
logger.Debug().Msg("Setting up HTTP server")
|
||||
httpServer := httpserver.NewServer(config, logger, conn, tokenGen, &staticFS)
|
||||
httpServer, err := setupHttpServer(&staticFS, config, logger, conn, tokenGen)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "setupHttpServer")
|
||||
}
|
||||
|
||||
// Runs the http server
|
||||
logger.Debug().Msg("Starting up the HTTP server")
|
||||
go func() {
|
||||
logger.Info().Str("address", httpServer.Addr).Msg("Listening for requests")
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Error().Err(err).Msg("Error listening and serving")
|
||||
}
|
||||
}()
|
||||
err = httpServer.Start()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "httpServer.Start")
|
||||
}
|
||||
|
||||
// Handles graceful shutdown
|
||||
var wg sync.WaitGroup
|
||||
@@ -80,9 +79,7 @@ func run(ctx context.Context, w io.Writer, args map[string]string, config *confi
|
||||
shutdownCtx := context.Background()
|
||||
shutdownCtx, cancel := context.WithTimeout(shutdownCtx, 10*time.Second)
|
||||
defer cancel()
|
||||
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
||||
logger.Error().Err(err).Msg("Error shutting down server")
|
||||
}
|
||||
httpServer.Shutdown(shutdownCtx)
|
||||
})
|
||||
wg.Wait()
|
||||
logger.Info().Msg("Shutting down")
|
||||
|
||||
Reference in New Issue
Block a user