Compare commits

...

5 Commits

Author SHA1 Message Date
darius
cf0d0a1644 docker registry to gitea
Some checks failed
build and deploy portfolio / build (pull_request) Failing after 33s
build and deploy portfolio / publish-docs (pull_request) Has been skipped
build and deploy portfolio / publish-portfolio (pull_request) Has been skipped
2025-02-24 00:21:51 +01:00
darius
2483ce5e20 Merge remote-tracking branch 'origin/refactor' into refactor
Some checks failed
build and deploy portfolio / build (pull_request) Successful in 38s
build and deploy portfolio / publish-docs (pull_request) Failing after 3s
build and deploy portfolio / publish-portfolio (pull_request) Failing after 3s
2025-02-24 00:16:39 +01:00
darius
a790b91041 small refactor 2025-02-24 00:16:27 +01:00
darius
12504fd789 small refactor 2025-02-24 00:15:10 +01:00
darius
5ffcd574cb fixed pipeline 2025-02-23 15:10:24 +01:00
12 changed files with 95 additions and 118 deletions

View File

@ -13,13 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker compose build
- name: Docker push
run: docker push docker.dariusklein.nl/portfolio
- name: Docker push
run: docker push docker.dariusklein.nl/portfolio-docs
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker compose build
- name: Docker push
run: docker push gitea.kleinsense.nl/dariusklein/portfolio:latest
- name: Docker push
run: docker push gitea.kleinsense.nl/dariusklein/portfolio-docs:latest
publish-docs:
@ -33,11 +33,11 @@ jobs:
- name: Docker remove
run: docker rm darius-portfolio-docs || true
- name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
run: docker login gitea.kleinsense.nl -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 gitea.kleinsense.nl/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 gitea.kleinsense.nl/dariusklein/portfolio-docs:latest
publish-portfolio:
@ -51,8 +51,8 @@ jobs:
- name: Docker remove
run: docker rm darius-portfolio-server || true
- name: Docker login
run: docker login 192.168.1.200:3000 -p ${{secrets.docker_password}} -u ${{secrets.docker_username}}
run: docker login gitea.kleinsense.nl -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 gitea.kleinsense.nl/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 gitea.kleinsense.nl/dariusklein/portfolio:latest

View File

@ -5,7 +5,7 @@ import (
"portfolio/api/handlers"
)
func ApiRoutes() *http.ServeMux {
func Routes() *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 {
err := json.NewDecoder(r.Body).Decode(&u)
if err != nil {
if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
InternalServerErrorHandler(w, err)
return
}
}
@ -60,7 +60,8 @@ func Login(w http.ResponseWriter, r *http.Request) {
} else {
UnauthorizedHandler(w)
return
println("unauthorized")
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,20 +1,6 @@
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: .
@ -24,10 +10,7 @@ services:
- "4000:4000"
- "4001:4001"
restart: unless-stopped
image: docker.dariusklein.nl/portfolio:latest
# depends_on:
# database:
# condition: service_healthy
image: gitea.kleinsense.nl/portfolio:latest
volumes:
- ./backup:/web/assets/json
@ -39,5 +22,5 @@ services:
ports:
- "4002:80"
restart: unless-stopped
image: docker.dariusklein.nl/portfolio-docs:latest
image: gitea.kleinsense.nl/portfolio-docs:latest

1
go.mod
View File

@ -24,6 +24,7 @@ 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,7 +1,9 @@
package main
import (
"github.com/joho/godotenv"
"github.com/rs/cors"
"log"
"net/http"
"portfolio/api"
"portfolio/database"
@ -9,20 +11,26 @@ 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.WebRoutes()
webMux := web.Routes()
// 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{
AllowedOrigins: []string{"http://localhost:4000", "https://*.dariusklein.nl", "https://*.portfolio.dariusklein.nl", "https://dariusklein.nl"},
@ -39,8 +47,15 @@ func main() {
})
//init api routes
apiMux := api.ApiRoutes()
apiMux := api.Routes()
//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"
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"),
b.Box(
Email(false, false, nil),

View File

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