Initial commit
This commit is contained in:
commit
7cbcab0d48
25 changed files with 25504 additions and 0 deletions
50
internal/auth/auth.go
Normal file
50
internal/auth/auth.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"log"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
envUsernameHash = "HUGOMARDBRINK_USERNAME"
|
||||
envPasswordHash = "HUGOMARDBRINK_PASSWORD"
|
||||
)
|
||||
|
||||
func BasicAuth(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return echo.HandlerFunc(func(c echo.Context) error {
|
||||
username, password, ok := c.Request().BasicAuth()
|
||||
|
||||
if !ok {
|
||||
c.Response().Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
|
||||
usernameHash := sha512.Sum512([]byte(username))
|
||||
passwordHash := sha512.Sum512([]byte(password))
|
||||
|
||||
expectedUsernameHash, err := hex.DecodeString(os.Getenv(envUsernameHash))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
expectedPasswordHash, err := hex.DecodeString(os.Getenv(envPasswordHash))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
usernameMatch := subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1
|
||||
passwordMatch := subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1
|
||||
|
||||
if usernameMatch && passwordMatch {
|
||||
return next(c)
|
||||
} else {
|
||||
c.Response().Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
})
|
||||
}
|
||||
6
internal/config/config.go
Normal file
6
internal/config/config.go
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package config
|
||||
|
||||
const (
|
||||
DatabaseFile = "./database/data.db"
|
||||
SeedFile = "./database/seed.sql"
|
||||
)
|
||||
67
internal/handlers/handlers.go
Normal file
67
internal/handlers/handlers.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"hugo.mardbrink.se/internal/models"
|
||||
)
|
||||
|
||||
func RegisterRoutes(e *echo.Echo, db *sql.DB) {
|
||||
e.GET("/", homePageHandler())
|
||||
e.GET("/projects", projectsPageHandler())
|
||||
e.GET("/articles", articlesPageHandler())
|
||||
}
|
||||
|
||||
func homePageHandler() echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
isHtmx := c.Request().Header.Get("HX-Request") == "true"
|
||||
c.Request().Header.Add("Vary", "HX-Request")
|
||||
p := models.Page{
|
||||
Title: "Hugo Mårdbrink",
|
||||
Description: "Home page of Hugo Mårdbrinks personal website.",
|
||||
IsHtmx: isHtmx,
|
||||
Breadcrumbs: models.Breadcrumbs{models.NewBreadcrumb("home", "/")}}
|
||||
hp := models.NewHomePage(p)
|
||||
|
||||
return c.Render(http.StatusOK, "home", hp)
|
||||
}
|
||||
}
|
||||
|
||||
func projectsPageHandler() echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
isHtmx := c.Request().Header.Get("HX-Request") == "true"
|
||||
c.Request().Header.Add("Vary", "HX-Request")
|
||||
|
||||
p := models.Page{
|
||||
Title: "Hugo Mårdbrink - Projects",
|
||||
Description: "Hobby projects by Hugo Mårdbrink.",
|
||||
IsHtmx: isHtmx,
|
||||
Breadcrumbs: models.Breadcrumbs{
|
||||
models.NewBreadcrumb("Home", "/"),
|
||||
models.NewBreadcrumb("projects", "/projects")}}
|
||||
pp := models.NewProjectPage(p)
|
||||
|
||||
return c.Render(http.StatusOK, "projects", pp)
|
||||
}
|
||||
}
|
||||
|
||||
func articlesPageHandler() echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
isHtmx := c.Request().Header.Get("HX-Request") == "true"
|
||||
c.Request().Header.Add("Vary", "HX-Request")
|
||||
|
||||
p := models.Page{
|
||||
Title: "Hugo Mårdbrink - Articles",
|
||||
Description: "Articles by Hugo Mårdbrink.",
|
||||
IsHtmx: isHtmx,
|
||||
Breadcrumbs: models.Breadcrumbs{
|
||||
models.NewBreadcrumb("Home", "/"),
|
||||
models.NewBreadcrumb("articles", "/articles")}}
|
||||
pp := models.NewProjectPage(p)
|
||||
|
||||
return c.Render(http.StatusOK, "articles", pp)
|
||||
}
|
||||
}
|
||||
53
internal/models/pages.go
Normal file
53
internal/models/pages.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package models
|
||||
|
||||
type Breadcrumb struct {
|
||||
Title string
|
||||
Route string
|
||||
}
|
||||
|
||||
type Breadcrumbs = []Breadcrumb
|
||||
|
||||
type Page struct {
|
||||
Title string
|
||||
Description string
|
||||
Breadcrumbs Breadcrumbs
|
||||
IsHtmx bool
|
||||
}
|
||||
|
||||
type HomePage struct {
|
||||
Page Page
|
||||
}
|
||||
|
||||
type ProjectPage struct {
|
||||
Page Page
|
||||
}
|
||||
|
||||
|
||||
func NewPage(title string, description string, breadcrumbs Breadcrumbs, isHtmx bool) Page {
|
||||
return Page{
|
||||
Title: title,
|
||||
Description: description,
|
||||
Breadcrumbs: breadcrumbs,
|
||||
IsHtmx: isHtmx,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBreadcrumb(title string, route string) Breadcrumb {
|
||||
return Breadcrumb{
|
||||
Title: title,
|
||||
Route: route,
|
||||
}
|
||||
}
|
||||
|
||||
func NewHomePage(page Page) HomePage {
|
||||
return HomePage{
|
||||
Page: page,
|
||||
}
|
||||
}
|
||||
|
||||
func NewProjectPage(page Page) ProjectPage {
|
||||
return ProjectPage{
|
||||
Page: page,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue