Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from fiber to chi #61

Merged
merged 14 commits into from
Jan 10, 2024
Merged
14 changes: 11 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
Expand All @@ -21,6 +18,17 @@ jobs:
with:
go-version: '1.21.5'

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 18

- name: Install dependencies
run: npm ci

- name: Compile css
run: make build-css

- name: Build
run: go build -v ./...

Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ push-image:
@docker tag visio:latest thewisepigeon/visio:latest
@docker push thewisepigeon/visio:latest

tailwind-compilation:
start-tailwind-compilation:
@npx tailwindcss -i ./assets/app.css -o ./public/output.css --minify --watch

build-css:
@npx tailwindcss -i ./assets/app.css -o ./public/output.css --minify

test:
@go test -v ./...
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/go-chi/chi/v5 v5.0.11 // indirect
github.com/gofiber/template v1.8.2 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA=
github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ=
Expand Down
85 changes: 71 additions & 14 deletions internal/handlers/app.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package handlers

import (
"github.com/gofiber/fiber/v2"
"encoding/json"
"html/template"
"log/slog"
"net/http"
"visio/internal/store"
"visio/internal/types"
)
Expand All @@ -19,27 +21,82 @@ func NewAppHandler(keys *store.Keys, logger *slog.Logger) *AppHandler {
}
}

func (h *AppHandler) GetLandingPage(c *fiber.Ctx) error {
return c.Render("index", fiber.Map{})
}

func (h *AppHandler) GetAuthPage(c *fiber.Ctx) error {
return c.Render("auth", fiber.Map{})
func (h *AppHandler) RenderLandingPage(w http.ResponseWriter, r *http.Request) {
templFiles := []string{
"views/layouts/base.html",
"views/home.html",
}
ts, err := template.ParseFiles(templFiles...)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
err = ts.ExecuteTemplate(w, "base", nil)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
}

func (h *AppHandler) GetHomePage(c *fiber.Ctx) error {
return c.Render("home", fiber.Map{})
func (h *AppHandler) RenderAuthPage(w http.ResponseWriter, r *http.Request) {
templateFiles := []string{
"views/layouts/base.html",
"views/auth.html",
}
ts, err := template.ParseFiles(templateFiles...)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
err = ts.ExecuteTemplate(w, "base", nil)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
}

func (h *AppHandler) GetKeysPage(c *fiber.Ctx) error {
currentUser, ok := c.Locals("currentUser").(*types.User)
func (h *AppHandler) GetKeysPage(w http.ResponseWriter, r *http.Request) {
currentUser, ok := r.Context().Value("currentUser").(*types.User)
if !ok {
return c.SendStatus(fiber.StatusUnauthorized)
http.Redirect(w, r, "/auth", http.StatusTemporaryRedirect)
return
}
userKeys, err := h.keys.GetByUserId(currentUser.Id)
if err != nil {
h.logger.Error(err.Error())
return c.SendStatus(fiber.StatusInternalServerError)
w.WriteHeader(http.StatusInternalServerError)
return
}
templateFiles := []string{
"views/layouts/app.html",
"views/keys.html",
}

ts, err := template.New("").Funcs(template.FuncMap{
"jsonify": func(v interface{}) string {
b, err := json.Marshal(v)
if err != nil {
return ""
}
return string(b)
},
}).ParseFiles(templateFiles...)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
templData := map[string]interface{}{
"Keys": userKeys,
}
err = ts.ExecuteTemplate(w, "app", templData)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
return c.Render("keys", fiber.Map{"Keys": userKeys}, "layouts/app")
}
89 changes: 51 additions & 38 deletions internal/handlers/auth.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package handlers

import (
"encoding/json"
"errors"
"fmt"
"github.com/oklog/ulid/v2"
"log/slog"
"net/http"
"time"
"visio/internal/store"
"visio/internal/types"
"visio/pkg"
"github.com/gofiber/fiber/v2"
"github.com/oklog/ulid/v2"
)

type AuthHandler struct {
Expand All @@ -26,83 +26,96 @@ func NewAuthHandler(usersStore *store.Users, sessionsStore *store.Sessions, logg
}
}

func (h *AuthHandler) Signup(c *fiber.Ctx) error {
reqPayload := new(struct {
func (h *AuthHandler) Authenticate(w http.ResponseWriter, r *http.Request) {
payload := new(struct {
Email string `json:"email"`
Password string `json:"password"`
})
action := c.Query("action")
if action == "" {
return c.SendStatus(fiber.ErrBadRequest.Code)
action := r.URL.Query().Get("action")
if action != "Login" && action != "Register" {
w.WriteHeader(http.StatusBadRequest)
return
}
if err := c.BodyParser(reqPayload); err != nil {
h.logger.Error(fmt.Sprintf("Error while parsing body: %v", err))
return c.SendStatus(fiber.ErrInternalServerError.Code)
err := json.NewDecoder(r.Body).Decode(payload)
if err != nil {
h.logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
switch action {
case "Register":
count, err := h.users.CountByEmail(reqPayload.Email)
count, err := h.users.CountByEmail(payload.Email)
if err != nil {
h.logger.Error(err.Error())
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
if count != 0 {
return c.SendStatus(fiber.ErrConflict.Code)
if count > 0 {
w.WriteHeader(http.StatusConflict)
return
}
hash, err := pkg.Hash(reqPayload.Password)
hash, err := pkg.Hash(payload.Password)
if err != nil {
h.logger.Error(err.Error())
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
newUser := &types.User{
Id: ulid.Make().String(),
Email: reqPayload.Email,
Password: hash,
SignupDate: time.Now().UTC(),
Id: ulid.Make().String(),
Email: payload.Email,
PasswordHash: hash,
SignupDate: time.Now().UTC().Format("January, 2 2006"),
}
err = h.users.Insert(newUser)
if err != nil {
h.logger.Error(err.Error())
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
sessionId := ulid.Make().String()
err = h.sessions.Create(sessionId, newUser.Id)
if err != nil {
h.logger.Error(err.Error())
c.Set("X-Err-Context", "ERR_SESSION_CREATION")
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
authCookie := &fiber.Cookie{
authCookie := &http.Cookie{
Name: "session",
Value: sessionId,
Path: "/",
}
c.Cookie(authCookie)
return c.SendStatus(fiber.StatusCreated)
http.SetCookie(w, authCookie)
w.WriteHeader(http.StatusCreated)
return
case "Login":
dbUser, err := h.users.GetByEmail(reqPayload.Email)
dbUser, err := h.users.GetByEmail(payload.Email)
if err != nil {
if errors.Is(err, types.ErrUserNotFound) {
return c.SendStatus(fiber.ErrBadRequest.Code)
w.WriteHeader(http.StatusBadRequest)
return
}
h.logger.Error(err.Error())
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !pkg.PasswordMatches(reqPayload.Password, dbUser.Password) {
return c.SendStatus(fiber.ErrBadRequest.Code)
if !pkg.PasswordMatches(payload.Password, dbUser.PasswordHash) {
w.WriteHeader(http.StatusBadRequest)
return
}
sessionId := ulid.Make().String()
err = h.sessions.Create(sessionId, dbUser.Id)
if err != nil {
h.logger.Error(err.Error())
c.Set("X-Err-Context", "ERR_SESSION_CREATION")
return c.SendStatus(fiber.ErrInternalServerError.Code)
w.WriteHeader(http.StatusInternalServerError)
return
}
authCookie := &fiber.Cookie{
authCookie := &http.Cookie{
Name: "session",
Value: sessionId,
Path: "/",
}
c.Cookie(authCookie)
return c.SendStatus(fiber.StatusOK)
http.SetCookie(w, authCookie)
w.WriteHeader(http.StatusOK)
return
}
return c.SendStatus(fiber.ErrBadRequest.Code)
}
Loading