refactor #1

Merged
DariusKlein merged 4 commits from refactor into master 2025-02-24 00:18:04 +01:00
12 changed files with 84 additions and 107 deletions

View File

@ -35,9 +35,9 @@ jobs:
- name: Docker login - name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}} run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
- name: Docker pull - name: Docker pull
run: docker pull 192.168.1.200:3000/DariusKlein/portfolio-docs:latest run: docker pull 192.168.1.200:3000/dariusklein/portfolio-docs:latest
- name: Docker run - name: Docker run
run: docker run --restart=always -dit -p 4002:80 --name darius-portfolio-docs 192.168.1.200:3000/DariusKlein/portfolio-docs:latest run: docker run --restart=always -dit -p 4002:80 --name darius-portfolio-docs 192.168.1.200:3000/dariusklein/portfolio-docs:latest
publish-portfolio: publish-portfolio:
@ -53,6 +53,6 @@ jobs:
- name: Docker login - name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}} run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
- name: Docker pull - name: Docker pull
run: docker pull 192.168.1.200:3000/DariusKlein/portfolio:latest run: docker pull 192.168.1.200:3000/dariusklein/portfolio:latest
- name: Docker run - name: Docker run
run: docker run --restart=always -dit -p 4001:4001 -p 4002:4002 --name darius-portfolio-server 192.168.1.200:3000/DariusKlein/portfolio:latest run: docker run --restart=always -dit -p 4001:4001 -p 4002:4002 --name darius-portfolio-server 192.168.1.200:3000/dariusklein/portfolio:latest

View File

@ -5,7 +5,7 @@ import (
"portfolio/api/handlers" "portfolio/api/handlers"
) )
func ApiRoutes() *http.ServeMux { func Routes() *http.ServeMux {
// Create a new request multiplexer // Create a new request multiplexer
// Take incoming requests and dispatch them to the matching webHandler // Take incoming requests and dispatch them to the matching webHandler
mux := http.NewServeMux() mux := http.NewServeMux()

View File

@ -22,9 +22,9 @@ func Login(w http.ResponseWriter, r *http.Request) {
Password: r.PostFormValue("password"), Password: r.PostFormValue("password"),
} }
} else { } else {
err := json.NewDecoder(r.Body).Decode(&u) if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
if err != nil {
InternalServerErrorHandler(w, err) InternalServerErrorHandler(w, err)
return
} }
} }
@ -60,7 +60,8 @@ func Login(w http.ResponseWriter, r *http.Request) {
} else { } else {
UnauthorizedHandler(w) UnauthorizedHandler(w)
return
println("unauthorized")
} }
} }

View File

@ -1,55 +1,38 @@
package handlers package handlers
import "net/http" import (
"log"
"net/http"
)
func InternalServerErrorHandler(w http.ResponseWriter, err error) { func InternalServerErrorHandler(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusInternalServerError) //set http status setError(w, http.StatusInternalServerError, err.Error())
_, err = w.Write([]byte(err.Error())) //set response message
if err != nil {
return
}
return
} }
func NotFoundHandler(w http.ResponseWriter) { func NotFoundHandler(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound) setError(w, http.StatusNotFound, "404 Not Found")
_, err := w.Write([]byte("404 Not Found"))
if err != nil {
return
}
} }
func BadRequestHandler(w http.ResponseWriter) { func BadRequestHandler(w http.ResponseWriter) {
w.WriteHeader(http.StatusBadRequest) setError(w, http.StatusBadRequest, "404 Not Found")
_, err := w.Write([]byte("400 Bad Request"))
if err != nil {
return
}
} }
func UnprocessableEntityHandler(w http.ResponseWriter, err error) { func UnprocessableEntityHandler(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusUnprocessableEntity) //set http status setError(w, http.StatusUnprocessableEntity, err.Error())
_, err = w.Write([]byte(err.Error())) //set response message
if err != nil {
return
}
return
} }
func UnauthorizedHandler(w http.ResponseWriter) { func UnauthorizedHandler(w http.ResponseWriter) {
w.WriteHeader(http.StatusUnauthorized) //set http status setError(w, http.StatusUnauthorized, "Unauthorized")
_, err := w.Write([]byte("Unauthorized")) //set response message
if err != nil {
return
}
return
} }
func NotImplementedHandler(w http.ResponseWriter) { func NotImplementedHandler(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotImplemented) //set http status setError(w, http.StatusNotImplemented, "WORK IN PROGRESS")
_, err := w.Write([]byte("WORK IN PROGRESS")) }
if err != nil {
return func setError(w http.ResponseWriter, httpStatus int, errorMessage string) {
w.WriteHeader(httpStatus)
if _, err := w.Write([]byte(errorMessage)); err != nil {
log.Println(err)
} }
return return
} }

View File

@ -3,7 +3,6 @@ package handlers
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"net/http" "net/http"
"os" "os"
"portfolio/api/service/jwt" "portfolio/api/service/jwt"
@ -24,14 +23,12 @@ func CreateProjectHandler(w http.ResponseWriter, r *http.Request) {
var p *ent.Project var p *ent.Project
err = json.NewDecoder(r.Body).Decode(&p) if err = json.NewDecoder(r.Body).Decode(&p); err != nil {
if err != nil {
InternalServerErrorHandler(w, err) InternalServerErrorHandler(w, err)
return return
} }
err = query.CreateProject(context.Background(), *p, id) if err = query.CreateProject(context.Background(), *p, id); err != nil {
if err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
return return
} }
@ -39,8 +36,7 @@ func CreateProjectHandler(w http.ResponseWriter, r *http.Request) {
func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) { func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) {
_, _, err := jwt.VerifyUser(r) if _, _, err := jwt.VerifyUser(r); err != nil {
if err != nil {
UnauthorizedHandler(w) UnauthorizedHandler(w)
return return
} }
@ -50,6 +46,7 @@ func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) {
projectID, err := strconv.Atoi(r.PathValue("id")) projectID, err := strconv.Atoi(r.PathValue("id"))
if err != nil { if err != nil {
BadRequestHandler(w) BadRequestHandler(w)
return
} }
p, err = query.GetFullProject(context.Background(), projectID) p, err = query.GetFullProject(context.Background(), projectID)
@ -58,14 +55,12 @@ func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
err = json.NewDecoder(r.Body).Decode(&p) if err = json.NewDecoder(r.Body).Decode(&p); err != nil {
if err != nil {
InternalServerErrorHandler(w, err) InternalServerErrorHandler(w, err)
return return
} }
err = query.UpdateProject(context.Background(), *p, projectID) if err = query.UpdateProject(context.Background(), *p, projectID); err != nil {
if err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
return return
} }
@ -73,19 +68,19 @@ func UpdateProjectHandler(w http.ResponseWriter, r *http.Request) {
func UpdateProjectsHandler(w http.ResponseWriter, r *http.Request) { func UpdateProjectsHandler(w http.ResponseWriter, r *http.Request) {
var newProjects []*ent.Project
var p []*ent.Project
var err error
isHtmx := r.Header.Get("HX-Request") isHtmx := r.Header.Get("HX-Request")
_, _, err := jwt.VerifyUser(r) if _, _, err := jwt.VerifyUser(r); err != nil {
if err != nil {
UnauthorizedHandler(w) UnauthorizedHandler(w)
return return
} }
var newProjects []*ent.Project
var p []*ent.Project
if isHtmx == "true" { if isHtmx == "true" {
p = parse.ParseProjectInput(r) p = parse.ProjectInput(r)
} else { } else {
p, err = query.GetFullProjects(context.Background()) p, err = query.GetFullProjects(context.Background())
@ -110,8 +105,7 @@ func UpdateProjectsHandler(w http.ResponseWriter, r *http.Request) {
} }
for _, project := range p { for _, project := range p {
err = query.UpdateProject(context.Background(), *project, project.ID) if err = query.UpdateProject(context.Background(), *project, project.ID); err != nil {
if err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
return return
} }
@ -134,8 +128,8 @@ func GetProjectHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(p) if err = json.NewEncoder(w).Encode(p); err != nil {
if err != nil { InternalServerErrorHandler(w, err)
return return
} }
} }
@ -150,14 +144,13 @@ func GetProjectsHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(p) if err = json.NewEncoder(w).Encode(p); err != nil {
if err != nil { InternalServerErrorHandler(w, err)
return return
} }
} }
func GetProjectsBackupHandler(w http.ResponseWriter, r *http.Request) { func GetProjectsBackupHandler(w http.ResponseWriter, r *http.Request) {
fmt.Print("test")
p, err := query.GetProjects(context.Background()) p, err := query.GetProjects(context.Background())
if err != nil { if err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
@ -168,14 +161,17 @@ func GetProjectsBackupHandler(w http.ResponseWriter, r *http.Request) {
backup, _ := json.Marshal(p) backup, _ := json.Marshal(p)
err = os.WriteFile("/web/assets/json/backup-"+strconv.Itoa(int(time.Now().Unix()))+".json", backup, 0644) if err = os.WriteFile(
if err != nil { "/web/assets/json/backup-"+strconv.Itoa(int(time.Now().Unix()))+".json",
backup,
0644,
); err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
return return
} }
err = json.NewEncoder(w).Encode(p) if err = json.NewEncoder(w).Encode(p); err != nil {
if err != nil { InternalServerErrorHandler(w, err)
return return
} }
} }

View File

@ -23,9 +23,9 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
//Role: user.Role(r.PostFormValue("role")), //Role: user.Role(r.PostFormValue("role")),
} }
} else { } else {
err := json.NewDecoder(r.Body).Decode(&u) if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
if err != nil {
InternalServerErrorHandler(w, err) InternalServerErrorHandler(w, err)
return
} }
} }
u.Password = "123" u.Password = "123"
@ -37,14 +37,13 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
//hash password //hash password
u.Password, _ = bcrypt.HashPassword(u.Password) u.Password, _ = bcrypt.HashPassword(u.Password)
err := query.CreateUser(context.Background(), *u) if err := query.CreateUser(context.Background(), *u); err != nil {
if err != nil {
UnprocessableEntityHandler(w, err) UnprocessableEntityHandler(w, err)
return return
} }
w.WriteHeader(http.StatusCreated)
_, err = w.Write([]byte("user created"))
w.WriteHeader(http.StatusCreated)
w.Write([]byte("user created"))
} }
func GetUserHandler(w http.ResponseWriter, r *http.Request) { func GetUserHandler(w http.ResponseWriter, r *http.Request) {
@ -62,8 +61,7 @@ func GetUserHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(User) if err = json.NewEncoder(w).Encode(User); err != nil {
if err != nil {
InternalServerErrorHandler(w, err) InternalServerErrorHandler(w, err)
return return
} }

View File

@ -11,7 +11,7 @@ import (
"strconv" "strconv"
) )
func ParseProjectInput(r *http.Request) []*ent.Project { func ProjectInput(r *http.Request) []*ent.Project {
b, err := io.ReadAll(r.Body) b, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)

View File

@ -1,20 +1,6 @@
version: '3.8' version: '3.8'
services: services:
# database:
# container_name: darius-portfolio-database
# image: postgres:alpine
# restart: always
# env_file:
# - .env
# ports:
# - "5432:5432"
# healthcheck:
# test: [ "CMD-SHELL", "pg_isready -U postgres" ]
# interval: 10s
# timeout: 5s
# retries: 5
portfolio: portfolio:
container_name: darius-portfolio-server container_name: darius-portfolio-server
build: . build: .
@ -25,9 +11,6 @@ services:
- "4001:4001" - "4001:4001"
restart: unless-stopped restart: unless-stopped
image: docker.dariusklein.nl/portfolio:latest image: docker.dariusklein.nl/portfolio:latest
# depends_on:
# database:
# condition: service_healthy
volumes: volumes:
- ./backup:/web/assets/json - ./backup:/web/assets/json

1
go.mod
View File

@ -24,6 +24,7 @@ require (
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl/v2 v2.23.0 // indirect github.com/hashicorp/hcl/v2 v2.23.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/zclconf/go-cty v1.16.2 // indirect github.com/zclconf/go-cty v1.16.2 // indirect
github.com/zclconf/go-cty-yaml v1.1.0 // indirect github.com/zclconf/go-cty-yaml v1.1.0 // indirect

37
main.go
View File

@ -1,7 +1,9 @@
package main package main
import ( import (
"github.com/joho/godotenv"
"github.com/rs/cors" "github.com/rs/cors"
"log"
"net/http" "net/http"
"portfolio/api" "portfolio/api"
"portfolio/database" "portfolio/database"
@ -9,20 +11,26 @@ import (
) )
func main() { func main() {
//// load .env in runtime environment // load .env in runtime environment
//err := godotenv.Load() err := godotenv.Load()
//if err != nil { if err != nil {
// log.Fatalf(".env not found: %v", err) log.Fatalf(".env not found: %v", err)
// return return
//} }
//connect to database and migrate //connect to database and migrate
database.DB() database.DB()
//init web routes //init web routes
webMux := web.WebRoutes() webMux := web.Routes()
// Run web server // Run web server
go http.ListenAndServe(":4000", cors.AllowAll().Handler(webMux)) go func() {
err = http.ListenAndServe(":4000", cors.AllowAll().Handler(webMux))
if err != nil {
log.Fatal(err)
}
}()
c := cors.New(cors.Options{ c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:4000", "https://*.dariusklein.nl", "https://*.portfolio.dariusklein.nl", "https://dariusklein.nl"}, AllowedOrigins: []string{"http://localhost:4000", "https://*.dariusklein.nl", "https://*.portfolio.dariusklein.nl", "https://dariusklein.nl"},
@ -39,8 +47,15 @@ func main() {
}) })
//init api routes //init api routes
apiMux := api.ApiRoutes() apiMux := api.Routes()
//run api server //run api server
http.ListenAndServe(":4001", c.Handler(apiMux)) go func() {
err = http.ListenAndServe(":4001", c.Handler(apiMux))
if err != nil {
log.Fatal(err)
}
}()
// block main thread
select {}
} }

View File

@ -12,7 +12,7 @@ var BaseUrl = "https://api.portfolio.dariusklein.nl"
// todo var BaseUrl = "http://localhost:4001" // todo var BaseUrl = "http://localhost:4001"
func Login() g.Node { func Login() g.Node {
return FormEl(hx.Post(BaseUrl+"/login"), //https://api.portfolio.dariusklein.nl/login return Form(hx.Post(BaseUrl+"/login"), //https://api.portfolio.dariusklein.nl/login
Class("max-w-xl m-auto py-32"), Class("max-w-xl m-auto py-32"),
b.Box( b.Box(
Email(false, false, nil), Email(false, false, nil),

View File

@ -5,7 +5,7 @@ import (
"portfolio/web/handlers" "portfolio/web/handlers"
) )
func WebRoutes() *http.ServeMux { func Routes() *http.ServeMux {
// Create a new request multiplexer // Create a new request multiplexer
// Take incoming requests and dispatch them to the matching webHandler // Take incoming requests and dispatch them to the matching webHandler
mux := http.NewServeMux() mux := http.NewServeMux()