Compare commits

..

No commits in common. "12504fd789b35f3d8cc18e6e8d48b0781e5e55c4" and "9705a8c655ed40e3b16d8ef40709c16f2d051636" have entirely different histories.

12 changed files with 122 additions and 99 deletions

View File

@ -35,9 +35,9 @@ jobs:
- name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
- 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
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:
@ -53,6 +53,6 @@ jobs:
- name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
- 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
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"
)
func Routes() *http.ServeMux {
func ApiRoutes() *http.ServeMux {
// Create a new request multiplexer
// Take incoming requests and dispatch them to the matching webHandler
mux := http.NewServeMux()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,20 @@
version: '3.8'
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:
container_name: darius-portfolio-server
build: .
@ -11,6 +25,9 @@ services:
- "4001:4001"
restart: unless-stopped
image: docker.dariusklein.nl/portfolio:latest
# depends_on:
# database:
# condition: service_healthy
volumes:
- ./backup:/web/assets/json

1
go.mod
View File

@ -24,7 +24,6 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.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/zclconf/go-cty v1.16.2 // indirect
github.com/zclconf/go-cty-yaml v1.1.0 // indirect

35
main.go
View File

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

View File

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

View File

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