diff --git a/kontor-echo/Containerfile b/kontor-echo/Containerfile
index bbb66d7..3a0ae9a 100644
--- a/kontor-echo/Containerfile
+++ b/kontor-echo/Containerfile
@@ -1,5 +1,5 @@
# ---------- Stage 1: Build ----------
-FROM docker.io/library/golang:1.25-alpine AS builder
+FROM docker.io/library/golang:1.26-alpine AS builder
# Set the working directory
WORKDIR /app
# Ensure a portable, static-ish binary
@@ -9,8 +9,12 @@ COPY go.mod go.sum ./
RUN go mod download
# Copy the source code
COPY . .
+ARG VERSION="dev"
+ARG COMMIT="unset"
+ARG DATE="unset"
# Build the Go application (strip debug info for smaller size)
-RUN go build -trimpath -ldflags="-s -w" -o kontor cmd/kontor/main.go
+RUN go build -trimpath -ldflags="-s -w -X kontor-api-echo/internal/globals.Version=${VERSION} -X kontor-api-echo/internal/globals.Commit=${COMMIT} -X kontor-api-echo/internal/globals.Date=${DATE}" -o kontor cmd/kontor-echo/main.go
+
# ---------- Stage 2: Final ----------
FROM alpine:latest
diff --git a/kontor-echo/assets/assets.go b/kontor-echo/assets/assets.go
new file mode 100644
index 0000000..c147543
--- /dev/null
+++ b/kontor-echo/assets/assets.go
@@ -0,0 +1,8 @@
+package assets
+
+import (
+ "embed"
+)
+
+//go:embed style/* icons/*
+var StaticFiles embed.FS
diff --git a/kontor-echo/assets/icons/cross.png b/kontor-echo/assets/icons/cross.png
new file mode 100644
index 0000000..6b9fa6d
Binary files /dev/null and b/kontor-echo/assets/icons/cross.png differ
diff --git a/kontor-echo/assets/icons/logo.png b/kontor-echo/assets/icons/logo.png
new file mode 100644
index 0000000..7499bdf
Binary files /dev/null and b/kontor-echo/assets/icons/logo.png differ
diff --git a/kontor-echo/assets/icons/tick.png b/kontor-echo/assets/icons/tick.png
new file mode 100644
index 0000000..2414885
Binary files /dev/null and b/kontor-echo/assets/icons/tick.png differ
diff --git a/kontor-echo/assets/style/main.css b/kontor-echo/assets/style/main.css
new file mode 100644
index 0000000..52ae177
--- /dev/null
+++ b/kontor-echo/assets/style/main.css
@@ -0,0 +1,174 @@
+* {
+ box-sizing: border-box;
+}
+
+body {
+ font-family: Arial;
+ padding: 10px;
+ background: lightgrey;
+ padding-top: 56px;
+ padding-bottom: 56px;
+}
+
+/* Header/Blog Title */
+.header {
+ padding: 30px;
+ text-align: center;
+ background-color: lightblue;
+}
+
+.header h1 {
+ font-size: 50px;
+}
+
+/* Style the top navigation bar */
+.topnav {
+ overflow: hidden;
+ background-color: darkgrey;
+}
+
+/* Style the topnav links */
+.topnav a {
+ float: left;
+ display: block;
+ color: #f2f2f2;
+ text-align: center;
+ padding: 14px 16px;
+ text-decoration: none;
+}
+
+/* Change color on hover */
+.topnav a:hover {
+ background-color: #ddd;
+ color: black;
+}
+
+.subnav {
+ overflow: hidden;
+ background-color: grey;
+}
+
+.subnav a {
+ float: left;
+ display: block;
+ color: #f2f2f2;
+ text-align: center;
+ padding: 14px 16px;
+ text-decoration: none;
+}
+
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+ padding-top: 10px;
+ padding-left: 20px;
+}
+
+.form-inline label {
+ margin: 5px 10px 5px 0;
+}
+
+.form-inline input {
+ padding-right: 50px;
+ margin-right: 10px;
+}
+
+.form-inline button {
+ padding: 10px 20px;
+ background-color: dodgerblue;
+ border: 1px solid #ddd;
+ color: white;
+ border-radius: 10px;
+}
+
+.form-inline button:hover {
+ background-color: royalblue;
+}
+
+.pill-nav a {
+ display: inline-block;
+ color: white;
+ background-color: dodgerblue;
+ text-align: center;
+ padding: 10px;
+ text-decoration: none;
+ border-radius: 10px;
+ margin-left: 20px;
+}
+
+/* Change the color of links on mouse-over */
+.pill-nav a:hover {
+ background-color: royalblue;
+ color: white;
+}
+
+/* Add a color to the active/current link */
+.pill-nav a.active {
+ background-color: royalblue;
+ color: white;
+}
+
+.maincolumn {
+ float:left;
+ width: 100%;
+}
+/* Create two unequal columns that floats next to each other */
+/* Left column */
+.leftcolumn {
+ float: left;
+ width: 75%;
+}
+
+/* Right column */
+.rightcolumn {
+ float: left;
+ width: 25%;
+ background-color: #f1f1f1;
+ padding-left: 20px;
+}
+
+/* Fake image */
+.fakeimg {
+ background-color: #aaa;
+ width: 100%;
+ padding: 20px;
+}
+
+/* Add a card effect for articles */
+.card {
+ background-color: white;
+ padding: 20px;
+ margin-top: 20px;
+}
+
+/* Clear floats after the columns */
+.row::after {
+ content: "";
+ display: table;
+ clear: both;
+}
+
+/* Footer */
+.footer {
+ padding: 20px;
+ text-align: center;
+ background: #ddd;
+ margin-top: 20px;
+}
+
+/* Responsive layout - when the screen is less than 800px wide, make the two columns stack on top of each other instead of next to each other */
+@media screen and (max-width: 800px) {
+ .leftcolumn, .rightcolumn {
+ width: 100%;
+ padding: 0;
+ }
+}
+
+/* Responsive layout - when the screen is less than 400px wide, make the navigation links stack on top of each other instead of next to each other */
+@media screen and (max-width: 400px) {
+ .topnav a {
+ float: none;
+ width: 100%;
+ }
+}
diff --git a/kontor-echo/cmd/kontor-echo/main.go b/kontor-echo/cmd/kontor-echo/main.go
index 58a690e..4bb8372 100644
--- a/kontor-echo/cmd/kontor-echo/main.go
+++ b/kontor-echo/cmd/kontor-echo/main.go
@@ -31,7 +31,8 @@ func main() {
defer stop()
sc := echo.StartConfig{
- Address: ":1323",
+ //Address: fmt.Sprintf(":%d", config.ServerConfig.Server.Port),
+ Address: ":8400",
GracefulTimeout: 10 * time.Second,
}
if err := sc.Start(ctx, e); err != nil {
diff --git a/kontor-echo/cmd/kontor/main.go b/kontor-echo/cmd/kontor/main.go
index aef6b85..9eebd62 100644
--- a/kontor-echo/cmd/kontor/main.go
+++ b/kontor-echo/cmd/kontor/main.go
@@ -20,7 +20,6 @@ func main() {
}
e := echo.New()
- e.GET("/health", handler.GetHealth)
e.POST("/login", handler.Login)
skipper := func(c echo.Context) bool {
@@ -47,7 +46,6 @@ func main() {
group := e.Group("/api")
group.Use(echojwt.WithConfig(echojwt.Config{SigningKey: []byte("secret")}))
handler.SetupComicRoutes(group)
- handler.SetupMediaRoutes(group)
e.Logger.Fatal(e.Start(":8400"))
log.Println("Kontor finished")
diff --git a/kontor-echo/go.mod b/kontor-echo/go.mod
index c295ed8..ad99b5a 100644
--- a/kontor-echo/go.mod
+++ b/kontor-echo/go.mod
@@ -6,18 +6,18 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/labstack/echo-jwt/v4 v4.4.0
- github.com/labstack/echo-jwt/v5 v5.0.2
github.com/labstack/echo/v4 v4.15.0
github.com/labstack/echo/v5 v5.4.4
github.com/stretchr/testify v1.11.1
github.com/uptrace/bun v1.3.0
- github.com/uptrace/bun/dialect/pgdialect v1.2.16
+ github.com/uptrace/bun/dialect/pgdialect v1.3.0
github.com/uptrace/bun/driver/pgdriver v1.2.16
golang.org/x/crypto v0.54.0
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
+ github.com/labstack/echo-jwt/v5 v5.0.2 // indirect
github.com/mattn/go-sqlite3 v1.14.34 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
@@ -42,12 +42,11 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
- github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
- github.com/spf13/cobra v1.10.2 // indirect
+ github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.1.0 // indirect
- github.com/spf13/viper v1.21.0 // indirect
+ github.com/spf13/viper v1.21.0
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0
@@ -60,7 +59,7 @@ require (
go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.yaml.in/yaml/v3 v3.0.6 // indirect
golang.org/x/net v0.57.0 // indirect
- golang.org/x/sys v0.49.0 // indirect
+ golang.org/x/sys v0.50.0 // indirect
golang.org/x/text v0.43.0 // indirect
golang.org/x/time v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/kontor-echo/go.sum b/kontor-echo/go.sum
index f8ba6c2..c10934c 100644
--- a/kontor-echo/go.sum
+++ b/kontor-echo/go.sum
@@ -5,6 +5,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
@@ -13,12 +15,18 @@ github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63Y
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
+github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo-jwt/v4 v4.4.0 h1:nrXaEnJupfc2R4XChcLRDyghhMZup77F8nIzHnBK19U=
@@ -49,11 +57,11 @@ github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
-github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
-github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
@@ -71,12 +79,10 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
-github.com/uptrace/bun v1.2.16 h1:QlObi6ZIK5Ao7kAALnh91HWYNZUBbVwye52fmlQM9kc=
-github.com/uptrace/bun v1.2.16/go.mod h1:jMoNg2n56ckaawi/O/J92BHaECmrz6IRjuMWqlMaMTM=
github.com/uptrace/bun v1.3.0 h1:hUcbfRpbQk4/upFSI+uZf6jSJw5A0lkIKt0XdpvbUZo=
github.com/uptrace/bun v1.3.0/go.mod h1:wNltaKJk4JtOt4SG5I5zmA7v0/Mzjh1+/S906Rayd3Y=
-github.com/uptrace/bun/dialect/pgdialect v1.2.16 h1:KFNZ0LxAyczKNfK/IJWMyaleO6eI9/Z5tUv3DE1NVL4=
-github.com/uptrace/bun/dialect/pgdialect v1.2.16/go.mod h1:IJdMeV4sLfh0LDUZl7TIxLI0LipF1vwTK3hBC7p5qLo=
+github.com/uptrace/bun/dialect/pgdialect v1.3.0 h1:0ZkGqGugxaPCxko4DV2f4d7i+FnM2Qj3rNpChfhiv54=
+github.com/uptrace/bun/dialect/pgdialect v1.3.0/go.mod h1:kP5HGEpAX8iJCqj3WHm04XnoeBPacdCN1P2HiwMtHpg=
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0 h1:XzxkORYksxkLsIQLJHFYUb3yDvqSQHzTungyKpJhHTw=
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0/go.mod h1:x2D1sY50Itio0I/FVdNe30oMUT2ObiAS+oILcMR+Wys=
github.com/uptrace/bun/driver/pgdriver v1.2.16 h1:b1kpXKUxtTSGYow5Vlsb+dKV3z0R7aSAJNfMfKp61ZU=
@@ -102,19 +108,21 @@ golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
+golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c=
+golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
+golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
+golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
-golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
-golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA=
-golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
-golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
-golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
+golang.org/x/sys v0.50.0 h1:dkKZEFTEKaLr1sjhs0WiKqoi8Jj5nHbS3Njmx1UoMJs=
+golang.org/x/sys v0.50.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
+golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI=
+golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -122,11 +130,31 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0=
mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY=
+modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
+modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
+modernc.org/ccgo/v4 v4.30.2 h1:4yPaaq9dXYXZ2V8s1UgrC3KIj580l2N4ClrLwnbv2so=
+modernc.org/ccgo/v4 v4.30.2/go.mod h1:yZMnhWEdW0qw3EtCndG1+ldRrVGS+bIwyWmAWzS0XEw=
+modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
+modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
+modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
+modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
+modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
+modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
+modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
+modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.68.0 h1:PJ5ikFOV5pwpW+VqCK1hKJuEWsonkIJhhIXyuF/91pQ=
modernc.org/libc v1.68.0/go.mod h1:NnKCYeoYgsEqnY3PgvNgAeaJnso968ygU8Z0DxjoEc0=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
+modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
+modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
+modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
+modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
+modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
+modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
+modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
diff --git a/kontor-echo/internal/config/config.go b/kontor-echo/internal/config/config.go
index 87b0a91..0f87b7b 100644
--- a/kontor-echo/internal/config/config.go
+++ b/kontor-echo/internal/config/config.go
@@ -138,8 +138,8 @@ func InitConfig() error {
viper.SetDefault("db.user", "kontor")
viper.SetDefault("db.password", "kontor")
viper.SetDefault("db.path", "data/kontor.db")
- viper.SetDefault("server.port", 8550)
- viper.SetDefault("gin.mode", "release")
+ viper.SetDefault("server.host", "127.0.0.1")
+ viper.SetDefault("server.port", 8400)
// Read the config file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
diff --git a/kontor-echo/internal/handlers/auth.go b/kontor-echo/internal/handlers/auth.go
new file mode 100644
index 0000000..7a7c6fa
--- /dev/null
+++ b/kontor-echo/internal/handlers/auth.go
@@ -0,0 +1,114 @@
+package handlers
+
+import (
+ "kontor-api-echo/internal/config"
+ "kontor-api-echo/internal/globals"
+ "kontor-api-echo/internal/helpers"
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "kontor-api-echo/internal/service"
+ "net/http"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type AuthHandler struct {
+ Service *service.AuthService
+ Secret []byte
+}
+
+func NewAuthHandler(db *bun.DB) *AuthHandler {
+ handler := &AuthHandler{Service: service.NewAuthService(repository.NewProfileRepository(db)), Secret: config.ServerConfig.ApiSecret}
+ return handler
+}
+
+func (handler *AuthHandler) Login(c *echo.Context) error {
+ var input models.LoginInput
+
+ if err := c.Bind(&input); err != nil {
+ return c.JSON(http.StatusBadRequest, map[string]any{"error": err.Error()})
+ }
+
+ profile_id, err := handler.Service.LoginCheck(input.Email, input.Password)
+
+ if err != nil {
+ return c.JSON(http.StatusBadRequest, map[string]any{"error": "username or password is incorrect."})
+ }
+
+ token, err := helpers.GenerateToken(profile_id)
+ logger := c.Logger()
+ if err != nil {
+ logger.Info("Login", "GenerateToken error", err.Error())
+ }
+ return c.JSON(http.StatusOK, map[string]any{"token": token})
+}
+
+func (handler *AuthHandler) LoginPage(c *echo.Context) error {
+ cookie, _ := c.Cookie(globals.UserKey)
+ user := cookie.Value
+ logger := c.Logger()
+ logger.Info("LoginPage", globals.UserKey, user)
+ data := globals.GetDefaultValues(user, "Please logout first")
+ if user != "" {
+ return c.Render(http.StatusBadRequest, "login", data)
+ }
+ data["message"] = ""
+ return c.Render(http.StatusOK, "login", data)
+}
+
+func (handler *AuthHandler) LoginPost(c *echo.Context) error {
+ cookie, _ := c.Cookie(globals.UserKey)
+ user := cookie.Value
+ logger := c.Logger()
+ logger.Info("LoginPost", "user", user)
+ data := globals.GetDefaultValues(user, "Please logout first")
+ if user != "" {
+ return c.Render(http.StatusBadRequest, "login", data)
+ }
+
+ username := c.FormValue("username")
+ password := c.FormValue("password")
+
+ if helpers.EmptyUserPass(username, password) {
+ data["message"] = "Parameters can't be empty"
+ c.Render(http.StatusBadRequest, "login", data)
+ }
+
+ profile_id, err := handler.Service.LoginCheck(username, password)
+ if err != nil {
+ data["message"] = "Incorrect username or password"
+ c.Render(http.StatusUnauthorized, "login", data)
+ }
+ c.SetCookie(&http.Cookie{
+ Name: globals.UserKey,
+ Value: profile_id,
+ MaxAge: 3600,
+ Path: "/",
+ Domain: "",
+ HttpOnly: true,
+ })
+ logger.Info("LoginPost: redirect to index")
+ return c.Redirect(http.StatusMovedPermanently, "/")
+}
+
+func (handler *AuthHandler) LogoutPage(c *echo.Context) error {
+ cookie, _ := c.Cookie(globals.UserKey)
+ user := cookie.Value
+ logger := c.Logger()
+ logger.Info("LogoutPage", globals.UserKey, user)
+ if user == "" {
+ logger.Info("Invalid session token")
+ return c.Redirect(http.StatusMovedPermanently, "/")
+ }
+ c.SetCookie(&http.Cookie{
+ Name: globals.UserKey,
+ Value: "",
+ MaxAge: -1, // Deletes the cookie immediately
+ Path: "/",
+ Domain: "",
+ HttpOnly: true,
+ })
+ logger.Info("LogoutPage: redirect to index page")
+ return c.Redirect(http.StatusMovedPermanently, "/")
+}
diff --git a/kontor-echo/internal/handlers/kontor.go b/kontor-echo/internal/handlers/kontor.go
new file mode 100644
index 0000000..88628eb
--- /dev/null
+++ b/kontor-echo/internal/handlers/kontor.go
@@ -0,0 +1,33 @@
+package handlers
+
+import (
+ "kontor-api-echo/internal/globals"
+ "net/http"
+ "time"
+
+ "github.com/labstack/echo/v5"
+)
+
+func Health(c *echo.Context) error {
+ return c.JSON(200, map[string]string{
+ "ok": "true",
+ "status": "healthy",
+ "version": globals.Version,
+ "time": time.Now().UTC().Format(time.RFC3339),
+ })
+}
+
+func Index(c *echo.Context) error {
+ logger := c.Logger()
+ cookie, err := c.Cookie(globals.UserKey)
+ user := ""
+ if err != nil {
+ logger.Info("error reading cookie", "error", err.Error())
+ } else {
+ user = cookie.Value
+ }
+
+ logger.Info("IndexGetHandler", globals.UserKey, user)
+ data := globals.GetDefaultValues(user, "This is an index page...")
+ return c.Render(http.StatusOK, "home", data)
+}
diff --git a/kontor-echo/internal/handlers/mail.go b/kontor-echo/internal/handlers/mail.go
new file mode 100644
index 0000000..8724258
--- /dev/null
+++ b/kontor-echo/internal/handlers/mail.go
@@ -0,0 +1,30 @@
+package handlers
+
+import (
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "kontor-api-echo/internal/service"
+ "net/http"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type MailHandler struct {
+ Service *service.MailService
+}
+
+func NewMailHandler(db *bun.DB) *MailHandler {
+ handler := &MailHandler{Service: service.NewMailService(repository.NewMailRepository(db))}
+ return handler
+}
+
+func (handler *MailHandler) List(c *echo.Context) {
+ mails, err := handler.Service.List(c.Request().Context())
+ if err != nil {
+ c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
+ return
+ }
+ dtos := models.ConvertMailsToDtos(mails)
+ c.JSON(http.StatusOK, dtos)
+}
diff --git a/kontor-echo/internal/handlers/mailaccount.go b/kontor-echo/internal/handlers/mailaccount.go
new file mode 100644
index 0000000..f64421c
--- /dev/null
+++ b/kontor-echo/internal/handlers/mailaccount.go
@@ -0,0 +1,30 @@
+package handlers
+
+import (
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "kontor-api-echo/internal/service"
+ "net/http"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type MailAccountHandler struct {
+ Service *service.MailAccountService
+}
+
+func NewMailAccountHandler(db *bun.DB) *MailAccountHandler {
+ handler := &MailAccountHandler{Service: service.NewMailAccountService(repository.NewMailAccountRepository(db))}
+ return handler
+}
+
+func (handler *MailAccountHandler) List(c *echo.Context) {
+ mailaccounts, err := handler.Service.List(c.Request().Context())
+ if err != nil {
+ c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
+ return
+ }
+ dtos := models.ConvertMailAccountsToDtos(mailaccounts)
+ c.JSON(http.StatusOK, dtos)
+}
diff --git a/kontor-echo/internal/handlers/media_actor.go b/kontor-echo/internal/handlers/media_actor.go
index e0a5fe8..556a662 100644
--- a/kontor-echo/internal/handlers/media_actor.go
+++ b/kontor-echo/internal/handlers/media_actor.go
@@ -67,35 +67,35 @@ func (handler *MediaActorHandler) Delete(c *echo.Context) {
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
-func (handler *MediaActorHandler) ListPage(c *echo.Context) {
+func (handler *MediaActorHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
actors, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return err
}
data := globals.GetDefaultValues(user, "MediaActors...")
data["actors"] = actors
c.Render(http.StatusOK, "media_actors", data)
+ return nil
}
-func (handler *MediaActorHandler) EditPage(c *echo.Context) {
+func (handler *MediaActorHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
//logger := slog.Get(c)
actor, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaActors...")
data["actor"] = actor
- c.Render(http.StatusOK, "actor_detail", data)
+ return c.Render(http.StatusOK, "actor_detail", data)
}
-func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaActorHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -103,8 +103,7 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
actor, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaActorHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaActorForm
if err := c.Bind(&form); err != nil {
@@ -113,15 +112,14 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
data["actor"] = actor
data["Form"] = form
data["Errors"] = err.Error()
- c.Render(http.StatusBadRequest, "actor_detail", data)
- return
+ return c.Render(http.StatusBadRequest, "actor_detail", data)
}
logger.Info("MediaActorHandler#UpdatePage", "actor", actor)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
- c.Redirect(http.StatusFound, globals.MediaActorLink)
+ return c.Redirect(http.StatusFound, globals.MediaActorLink)
}
-func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
+func (handler *MediaActorHandler) DeletePage(c *echo.Context) error {
//session := sessions.Default(c)
//user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -129,9 +127,9 @@ func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
//actor, err := handler.Service.Get(c.Request.Context(), id)
// if err != nil {
// logger.Info("MediaActorHandler#DeletePage", "error", err.Error())
- // c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+ // c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
// return
// }
logger.Info("MediaActorHandler#DeletePage", "actor", id)
- c.Redirect(http.StatusFound, globals.MediaActorLink)
+ return c.Redirect(http.StatusFound, globals.MediaActorLink)
}
diff --git a/kontor-echo/internal/handlers/media_article.go b/kontor-echo/internal/handlers/media_article.go
index 2c38b1c..b013985 100644
--- a/kontor-echo/internal/handlers/media_article.go
+++ b/kontor-echo/internal/handlers/media_article.go
@@ -22,44 +22,41 @@ func NewMediaArticleHandler(db *bun.DB) *MediaArticleHandler {
return mediaFileHandler
}
-func (handler *MediaArticleHandler) List(c *echo.Context) {
+func (handler *MediaArticleHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaArticleHandler#List")
articles, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaArticlesToDtos(articles)
- c.JSON(http.StatusOK, dtos)
+ return c.JSON(http.StatusOK, dtos)
}
-func (handler *MediaArticleHandler) Delete(c *echo.Context) {
+func (handler *MediaArticleHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
- c.JSON(http.StatusOK, map[string]string{"ok": "true"})
+ return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
-func (handler *MediaArticleHandler) ListPage(c *echo.Context) {
+func (handler *MediaArticleHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
files, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaArticles...")
data["title"] = "Kontor MediaArticles"
data["media_links"] = files
data["MediaLinksUrl"] = globals.MediaArticleLink
- c.Render(http.StatusOK, "media_links", data)
+ return c.Render(http.StatusOK, "media_links", data)
}
-func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
+func (handler *MediaArticleHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -67,16 +64,15 @@ func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#EditPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaArticleHandler#EditPage", "media_file", media_file)
data := globals.GetDefaultValues(user, "MediaArticle Details...")
data["lofi"] = media_file
- c.Render(http.StatusOK, "lofi_detail", data)
+ return c.Render(http.StatusOK, "lofi_detail", data)
}
-func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -84,8 +80,7 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
media_article, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaArticleForm
if err := c.Bind(&form); err != nil {
@@ -93,23 +88,21 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaArticle Details...")
data["Form"] = form
data["Errors"] = err.Error()
- c.Render(http.StatusBadRequest, "lofi_detail", data)
- return
+ return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaArticleHandler#UpdatePage", "media_article", media_article)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
- c.Redirect(http.StatusFound, globals.MediaArticleLink)
+ return c.Redirect(http.StatusFound, globals.MediaArticleLink)
}
-func (handler *MediaArticleHandler) DeletePage(c *echo.Context) {
+func (handler *MediaArticleHandler) DeletePage(c *echo.Context) error {
id := c.Param("id")
logger := c.Logger()
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaArticleHandler#DeletePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaArticleHandler#DeletePage", "lofi", id)
- c.Redirect(http.StatusFound, globals.MediaArticleLink)
+ return c.Redirect(http.StatusFound, globals.MediaArticleLink)
}
diff --git a/kontor-echo/internal/handlers/media_file.go b/kontor-echo/internal/handlers/media_file.go
index b93c9ea..a2ce9de 100644
--- a/kontor-echo/internal/handlers/media_file.go
+++ b/kontor-echo/internal/handlers/media_file.go
@@ -22,59 +22,57 @@ func NewMediaFileHandler(db *bun.DB) *MediaFileHandler {
return mediaFileHandler
}
-func (handler *MediaFileHandler) List(c *echo.Context) {
+func (handler *MediaFileHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaFileHandler#List")
files, err := handler.Service.List(c.Request().Context())
if err != nil {
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return err
}
dtos := models.ConvertMediaFilesToDtos(files)
- c.JSON(http.StatusOK, dtos)
+ return c.JSON(http.StatusOK, dtos)
}
-func (handler *MediaFileHandler) Add(c *echo.Context) {
+func (handler *MediaFileHandler) Add(c *echo.Context) error {
var input models.MediaFileAdd
if err := c.Bind(&input); err != nil {
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
- return
+ return err
}
lofi, err := handler.Service.Add(c.Request().Context(), input.Url)
if err != nil {
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not added"})
- return
+ return err
}
- c.JSON(http.StatusOK, lofi)
+ return c.JSON(http.StatusOK, lofi)
}
-func (handler *MediaFileHandler) Delete(c *echo.Context) {
+func (handler *MediaFileHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
- c.JSON(http.StatusOK, map[string]string{"ok": "true"})
+ return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
-func (handler *MediaFileHandler) ListPage(c *echo.Context) {
+func (handler *MediaFileHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
files, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
data := globals.GetDefaultValues(user, "MediaFiles...")
data["title"] = "Kontor MediaFiles"
data["media_links"] = files
data["MediaLinksUrl"] = globals.MediaVideoLink
- c.Render(http.StatusOK, "media_links", data)
+ return c.Render(http.StatusOK, "media_links", data)
}
-func (handler *MediaFileHandler) EditPage(c *echo.Context) {
+func (handler *MediaFileHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -82,16 +80,15 @@ func (handler *MediaFileHandler) EditPage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#EditPage", "media_file", media_file)
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["lofi"] = media_file
- c.Render(http.StatusOK, "lofi_detail", data)
+ return c.Render(http.StatusOK, "lofi_detail", data)
}
-func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaFileHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -99,8 +96,7 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
media_file, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaFileHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaFileForm
if err := c.Bind(&form); err != nil {
@@ -108,15 +104,14 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["Form"] = form
data["Errors"] = err.Error()
- c.Render(http.StatusBadRequest, "lofi_detail", data)
- return
+ return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaFileHandler#UpdatePage", "media_file", media_file)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
- c.Redirect(http.StatusFound, globals.MediaFileLink)
+ return c.Redirect(http.StatusFound, globals.MediaFileLink)
}
-func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
+func (handler *MediaFileHandler) DeletePage(c *echo.Context) error {
//session := sessions.Default(c)
//user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -124,9 +119,8 @@ func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaFileHandler#DeletePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaFileHandler#DeletePage", "lofi", id)
- c.Redirect(http.StatusFound, globals.MediaFileLink)
+ return c.Redirect(http.StatusFound, globals.MediaFileLink)
}
diff --git a/kontor-echo/internal/handlers/media_lofi.go b/kontor-echo/internal/handlers/media_lofi.go
index 9916eb8..9e5d68c 100644
--- a/kontor-echo/internal/handlers/media_lofi.go
+++ b/kontor-echo/internal/handlers/media_lofi.go
@@ -59,33 +59,31 @@ func (handler *MediaLoFiHandler) Add(c *echo.Context) {
c.JSON(http.StatusOK, lofi)
}
-func (handler *MediaLoFiHandler) Update(c *echo.Context) {
+func (handler *MediaLoFiHandler) Update(c *echo.Context) error {
var input models.MediaLoFiDTO
if err := c.Bind(&input); err != nil {
- c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
lofi, err := handler.Service.Update(c.Request().Context(), input)
if err != nil {
logger := c.Logger()
logger.Info("MediaLoFiHandler#Update", "error", err.Error())
- c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
}
- c.JSON(http.StatusOK, lofi)
+ return c.JSON(http.StatusOK, lofi)
}
-func (handler *MediaLoFiHandler) Delete(c *echo.Context) {
+
+func (handler *MediaLoFiHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
}
- c.JSON(http.StatusOK, map[string]string{"ok": "true"})
+ return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
-func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
+func (handler *MediaLoFiHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
@@ -113,8 +111,7 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
lofis, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaLoFiHandler#ListPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
data := globals.GetDefaultValues(user, "MediaFiles...")
@@ -122,10 +119,10 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
data["isReview"] = review
data["isDownload"] = download
data["MediaLinksUrl"] = globals.MediaLofiLink
- c.Render(http.StatusOK, "media_links", data)
+ return c.Render(http.StatusOK, "media_links", data)
}
-func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
+func (handler *MediaLoFiHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -146,25 +143,23 @@ func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
lofi, err = handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
}
logger.Info("MediaLoFiHandler#EditPage", "lofi", lofi)
data := globals.GetDefaultValues(user, "MediaLofis...")
data["media"] = lofi
data["MediaLinksUrl"] = globals.MediaLofiLink
- c.Render(http.StatusOK, "media_detail", data)
+ return c.Render(http.StatusOK, "media_detail", data)
}
-func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
+func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) error {
id := c.Param("id")
logger := c.Logger()
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
- c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
- return
+ return c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
}
lofi.Review = !lofi.Review
handler.Service.Update(c.Request().Context(), lofi.ConvertMediaLoFiToDTO())
@@ -174,17 +169,16 @@ func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
lofis, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
data := globals.GetDefaultValues(user, "MediaLofis...")
data["lofis"] = lofis
- //c.HTML(http.StatusOK, "lofi", data)
- c.Redirect(http.StatusCreated, globals.MediaLofiLink)
+ //c.Render(http.StatusOK, "lofi", data)
+ return c.Redirect(http.StatusCreated, globals.MediaLofiLink)
}
-func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -192,25 +186,23 @@ func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaLoFiForm
if err := c.Bind(&form); err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
- c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
+ return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
"Form": form,
"Errors": err.Error(),
"user": user,
})
- return
}
logger.Info("MediaLoFiHandler#UpdatePage", "lofi", lofi)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
- c.Redirect(http.StatusFound, globals.MediaLofiLink)
+ return c.Redirect(http.StatusFound, globals.MediaLofiLink)
}
-func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
+func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -218,11 +210,10 @@ func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
lofi, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#DeletePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaLoFiHandler#DeletePage", "lofi", id)
- c.Render(http.StatusOK, "lofi_delete", map[string]any{
+ return c.Render(http.StatusOK, "lofi_delete", map[string]any{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
diff --git a/kontor-echo/internal/handlers/media_music.go b/kontor-echo/internal/handlers/media_music.go
index 47d3a4d..445b872 100644
--- a/kontor-echo/internal/handlers/media_music.go
+++ b/kontor-echo/internal/handlers/media_music.go
@@ -22,68 +22,62 @@ func NewMediaMusicHandler(db *bun.DB) *MediaMusicHandler {
return mediaMusicHandler
}
-func (handler *MediaMusicHandler) List(c *echo.Context) {
+func (handler *MediaMusicHandler) List(c *echo.Context) error {
musics, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaMusicsToDtos(musics)
- c.JSON(http.StatusOK, dtos)
+ return c.JSON(http.StatusOK, dtos)
}
-func (handler *MediaMusicHandler) Get(c *echo.Context) {
+func (handler *MediaMusicHandler) Get(c *echo.Context) error {
id := c.Param("id")
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
}
- c.JSON(http.StatusOK, music)
+ return c.JSON(http.StatusOK, music)
}
-func (handler *MediaMusicHandler) Add(c *echo.Context) {
+func (handler *MediaMusicHandler) Add(c *echo.Context) error {
var input models.MediaLofiAdd
if err := c.Bind(&input); err != nil {
- c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
music, err := handler.Service.Add(c.Request().Context(), input.Url)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
}
- c.JSON(http.StatusOK, music)
+ return c.JSON(http.StatusOK, music)
}
-func (handler *MediaMusicHandler) Update(c *echo.Context) {
+func (handler *MediaMusicHandler) Update(c *echo.Context) error {
var input models.MediaMusicDTO
if err := c.Bind(&input); err != nil {
- c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
music, err := handler.Service.Update(c.Request().Context(), input)
if err != nil {
logger := c.Logger()
logger.Info("MediaMusicHandler#Update", "error", err.Error())
- c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
}
- c.JSON(http.StatusOK, music)
+ return c.JSON(http.StatusOK, music)
}
-func (handler *MediaMusicHandler) Delete(c *echo.Context) {
+
+func (handler *MediaMusicHandler) Delete(c *echo.Context) error {
id := c.Param("id")
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
- c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
- return
+ return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
}
- c.JSON(http.StatusOK, map[string]string{"ok": "true"})
+ return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
}
-func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
+func (handler *MediaMusicHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
@@ -111,8 +105,7 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
musics, err := handler.Service.List(c.Request().Context())
if err != nil {
logger.Info("MediaMusicHandler#ListPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#ListPage", "MediaMusic count", len(musics))
data := globals.GetDefaultValues(user, "MediaMusic...")
@@ -120,10 +113,10 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
data["MediaLinksUrl"] = globals.MediaMusicLink
data["isReview"] = review
data["isDownload"] = download
- c.Render(http.StatusOK, "media_links", data)
+ return c.Render(http.StatusOK, "media_links", data)
}
-func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
+func (handler *MediaMusicHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -131,16 +124,15 @@ func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#EditPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#EditPage", "music", music)
data := globals.GetDefaultValues(user, "MediaMusic...")
data["lofi"] = music
- c.Render(http.StatusOK, "lofi_detail", data)
+ return c.Render(http.StatusOK, "lofi_detail", data)
}
-func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -148,8 +140,7 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
music, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaMusicForm
if err := c.Bind(&form); err != nil {
@@ -157,15 +148,14 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
data := globals.GetDefaultValues(user, "MediaMusic...")
data["Form"] = form
data["Errors"] = err.Error()
- c.Render(http.StatusBadRequest, "lofi_detail", data)
- return
+ return c.Render(http.StatusBadRequest, "lofi_detail", data)
}
logger.Info("MediaMusicHandler#UpdatePage", "music", music)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
- c.Redirect(http.StatusFound, globals.MediaMusicLink)
+ return c.Redirect(http.StatusFound, globals.MediaMusicLink)
}
-func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
+func (handler *MediaMusicHandler) DeletePage(c *echo.Context) error {
// session := sessions.Default(c)
// user := session.Get(globals.UserKey)
id := c.Param("id")
@@ -173,9 +163,8 @@ func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
err := handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaMusicHandler#DeletePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaMusicHandler#DeletePage", "music", id)
- c.Redirect(http.StatusFound, globals.MediaMusicLink)
+ return c.Redirect(http.StatusFound, globals.MediaMusicLink)
}
diff --git a/kontor-echo/internal/handlers/media_video.go b/kontor-echo/internal/handlers/media_video.go
index 563ecd7..2e1e5d4 100644
--- a/kontor-echo/internal/handlers/media_video.go
+++ b/kontor-echo/internal/handlers/media_video.go
@@ -20,36 +20,34 @@ func NewMediaVideoHandler(db *bun.DB) *MediaVideoHandler {
return handler
}
-func (handler *MediaVideoHandler) List(c *echo.Context) {
+func (handler *MediaVideoHandler) List(c *echo.Context) error {
logger := c.Logger()
logger.Info("MediaVideoHandler#List")
videos, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
dtos := models.ConvertMediaVideosToDtos(videos)
- c.JSON(http.StatusOK, dtos)
+ return c.JSON(http.StatusOK, dtos)
}
-func (handler *MediaVideoHandler) ListPage(c *echo.Context) {
+func (handler *MediaVideoHandler) ListPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
logger := c.Logger()
videos, err := handler.Service.List(c.Request().Context())
if err != nil {
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#ListPage", "videos count", len(videos))
data := globals.GetDefaultValues(user, "MediaVideos...")
data["title"] = "Kontor MediaVideos"
data["media_links"] = videos
data["MediaLinksUrl"] = globals.MediaVideoLink
- c.Render(http.StatusOK, "media_links", data)
+ return c.Render(http.StatusOK, "media_links", data)
}
-func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
+func (handler *MediaVideoHandler) EditPage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -57,16 +55,15 @@ func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
video, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#EditPage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#EditPage", "lofi", video)
data := globals.GetDefaultValues(user, "MediaLofis...")
data["lofi"] = video
- c.Render(http.StatusOK, "lofi_detail", data)
+ return c.Render(http.StatusOK, "lofi_detail", data)
}
-func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
+func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -74,25 +71,23 @@ func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
video, err := handler.Service.Get(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
var form models.MediaVideoForm
if err := c.Bind(&form); err != nil {
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
- c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
+ return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
"Form": form,
"Errors": err.Error(),
"user": user,
})
- return
}
logger.Info("MediaVideoHandler#UpdatePage", "lofi", video)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
- c.Redirect(http.StatusFound, globals.MediaVideoLink)
+ return c.Redirect(http.StatusFound, globals.MediaVideoLink)
}
-func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
+func (handler *MediaVideoHandler) DeletePage(c *echo.Context) error {
cookie, err := c.Cookie(globals.UserKey)
user := cookie.Value
id := c.Param("id")
@@ -100,11 +95,10 @@ func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
err = handler.Service.Delete(c.Request().Context(), id)
if err != nil {
logger.Info("MediaVideoHandler#DeletePage", "error", err.Error())
- c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
- return
+ return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
logger.Info("MediaVideoHandler#DeletePage", "video", id)
- c.Render(http.StatusOK, "lofi_delete", map[string]string{
+ return c.Render(http.StatusOK, "lofi_delete", map[string]string{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
diff --git a/kontor-echo/internal/handlers/token.go b/kontor-echo/internal/handlers/token.go
new file mode 100644
index 0000000..32f7b42
--- /dev/null
+++ b/kontor-echo/internal/handlers/token.go
@@ -0,0 +1,30 @@
+package handlers
+
+import (
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "kontor-api-echo/internal/service"
+ "net/http"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type TokenHandler struct {
+ Service *service.TokenService
+}
+
+func NewTokenHandler(db *bun.DB) *TokenHandler {
+ handler := &TokenHandler{Service: service.NewTokenService(repository.NewTokenRepository(db))}
+ return handler
+}
+
+func (handler *TokenHandler) List(c *echo.Context) {
+ tokens, err := handler.Service.List(c.Request().Context())
+ if err != nil {
+ c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
+ return
+ }
+ dtos := models.ConvertTokensToDtos(tokens)
+ c.JSON(http.StatusOK, dtos)
+}
diff --git a/kontor-echo/internal/helpers/auth.go b/kontor-echo/internal/helpers/auth.go
new file mode 100644
index 0000000..5a43c71
--- /dev/null
+++ b/kontor-echo/internal/helpers/auth.go
@@ -0,0 +1,7 @@
+package helpers
+
+import "strings"
+
+func EmptyUserPass(username, password string) bool {
+ return strings.Trim(username, " ") == "" || strings.Trim(password, " ") == ""
+}
diff --git a/kontor-echo/internal/helpers/token.go b/kontor-echo/internal/helpers/token.go
new file mode 100644
index 0000000..7a85e88
--- /dev/null
+++ b/kontor-echo/internal/helpers/token.go
@@ -0,0 +1,88 @@
+package helpers
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/golang-jwt/jwt/v5"
+ "github.com/labstack/echo/v5"
+ "github.com/spf13/viper"
+)
+
+func GenerateToken(profile_id string) (string, error) {
+
+ // token_lifespan := viper.GetInt("token_hour_lifespan")
+
+ claims := jwt.MapClaims{
+ "name": "Thomas Peetz",
+ "admin": true,
+ "authorized": true,
+ "sub": profile_id,
+ "exp": time.Now().Add(time.Hour * 72).Unix(),
+ }
+ // claims["authorized"] = true
+ // claims["profile_id"] = profile_id
+ // claims["exp"] = time.Now().Add(time.Hour * time.Duration(token_lifespan)).Unix()
+ token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+
+ return token.SignedString([]byte(viper.GetString("api_secret")))
+
+}
+
+func TokenValid(c *echo.Context) error {
+ logger := c.Logger()
+
+ tokenString := ExtractToken(c)
+ _, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+ if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
+ logger.Info("TokenValid", "Unexpected signing method", token.Header["alg"])
+ return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
+ }
+ return []byte(viper.GetString("api_secret")), nil
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func ExtractToken(c *echo.Context) string {
+ logger := c.Logger()
+
+ token := c.QueryParam("token")
+ if token != "" {
+ logger.Info("ExtractToken", "token from query", token)
+ return token
+ }
+ bearerToken := c.Request().Header.Get("Authorization")
+ if len(strings.Split(bearerToken, " ")) == 2 {
+ logger.Info("ExtractToken", "token from query", token)
+
+ return strings.Split(bearerToken, " ")[1]
+ }
+ return ""
+}
+
+func ExtractTokenID(c *echo.Context) (string, error) {
+
+ tokenString := ExtractToken(c)
+ token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
+ if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
+ return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
+ }
+ return []byte(viper.GetString("api_secret")), nil
+ })
+ if err != nil {
+ return "", err
+ }
+ claims, ok := token.Claims.(jwt.MapClaims)
+ if ok && token.Valid {
+ uid, ok := claims["profile_id"].(string)
+ if !ok {
+ return "", err
+ }
+ return uid, nil
+ }
+ return "", nil
+}
diff --git a/kontor-echo/internal/helpers/url.go b/kontor-echo/internal/helpers/url.go
new file mode 100644
index 0000000..4e94074
--- /dev/null
+++ b/kontor-echo/internal/helpers/url.go
@@ -0,0 +1,69 @@
+package helpers
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "log/slog"
+ "net/http"
+ "net/url"
+)
+
+func StripUrl(webLink string, keepParam string) string {
+ u, err := url.Parse(webLink)
+ if err != nil {
+ slog.Info("StripUrl", "error", err)
+ return webLink
+ }
+ values := u.Query()
+ for key := range values {
+ if key != keepParam {
+ values.Del(key)
+ }
+ }
+ u.RawQuery = values.Encode()
+ return u.String()
+}
+
+func GetParam(webLink string, param string) string {
+ u, err := url.Parse(webLink)
+ if err != nil {
+ slog.Info("StripUrl", "error", err)
+ return webLink
+ }
+ values := u.Query()
+ for key := range values {
+ if key == param {
+ return values.Get(key)
+ }
+ }
+ return ""
+}
+
+type OEmbedResponse struct {
+ Title string `json:"title"`
+}
+
+func GetVideoTitle(videoUrl string) (string, error) {
+ videoID := GetParam(videoUrl, "v")
+ // Construct the oEmbed URL
+ url := fmt.Sprintf("https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=%s&format=json", videoID)
+
+ resp, err := http.Get(url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return "", err
+ }
+
+ var data OEmbedResponse
+ if err := json.Unmarshal(body, &data); err != nil {
+ return "", err
+ }
+
+ return data.Title, nil
+}
diff --git a/kontor-echo/internal/models/mail.go b/kontor-echo/internal/models/mail.go
new file mode 100644
index 0000000..c5e630d
--- /dev/null
+++ b/kontor-echo/internal/models/mail.go
@@ -0,0 +1,73 @@
+package models
+
+import (
+ "kontor-api-echo/internal/helpers"
+ "time"
+
+ "github.com/uptrace/bun"
+)
+
+type Mail struct {
+ bun.BaseModel `bun:"table:mail"`
+
+ ID string `bun:"id,pk"`
+ CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
+ DeletedAt *time.Time `bun:"deleted_date,nullzero"`
+ Version int `bun:"version,default:0"`
+ Folder string `bun:"folder"`
+ Subject string `bun:"subject"`
+ Body string `bun:"body"`
+ SendAt time.Time `bun:"sent_date"`
+ ReceivedAt time.Time `bun:"received_date"`
+}
+
+type MailDTO struct {
+ ID string `json:"id" binding:"required"`
+ CreatedAt helpers.KontorTime `json:"created_date"`
+ UpdatedAt helpers.KontorTime `json:"last_modified_date"`
+ DeletedAt *time.Time `json:"deleted_date.omitempty"`
+ Version int `json:"version"`
+ Folder string `json:"folder"`
+ Subject string `json:"subject"`
+ Body string `json:"body"`
+ SendAt time.Time `json:"sent_date"`
+ ReceivedAt time.Time `json:"received_date"`
+}
+
+func (dto MailDTO) ConvertDTOToModel() Mail {
+ model := Mail{
+ ID: dto.ID,
+ CreatedAt: dto.CreatedAt.Time,
+ UpdatedAt: dto.UpdatedAt.Time,
+ DeletedAt: dto.DeletedAt,
+ Version: dto.Version,
+ Folder: dto.Folder,
+ Subject: dto.Subject,
+ Body: dto.Body,
+ SendAt: dto.SendAt,
+ ReceivedAt: dto.ReceivedAt,
+ }
+ return model
+}
+
+func ConvertMailsToDtos(mails []Mail) []MailDTO {
+ dtos := make([]MailDTO, len(mails))
+ for i, mail := range mails {
+ dtos[i] = MailDTO{
+ ID: mail.ID,
+ CreatedAt: helpers.KontorTime{Time: mail.CreatedAt},
+ UpdatedAt: helpers.KontorTime{Time: mail.UpdatedAt},
+ DeletedAt: mail.DeletedAt,
+ Version: mail.Version,
+ Folder: mail.Folder,
+ Subject: mail.Subject,
+ Body: mail.Body,
+ SendAt: mail.SendAt,
+ ReceivedAt: mail.ReceivedAt,
+ }
+ }
+ return dtos
+}
+
+type MailDTOList []MailDTO
diff --git a/kontor-echo/internal/models/mailaccount.go b/kontor-echo/internal/models/mailaccount.go
new file mode 100644
index 0000000..68f1075
--- /dev/null
+++ b/kontor-echo/internal/models/mailaccount.go
@@ -0,0 +1,77 @@
+package models
+
+import (
+ "kontor-api-echo/internal/helpers"
+ "time"
+
+ "github.com/uptrace/bun"
+)
+
+type MailAccount struct {
+ bun.BaseModel `bun:"table:mail_account"`
+
+ ID string `bun:"id,pk"`
+ CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
+ DeletedAt *time.Time `bun:"deleted_date,nullzero"`
+ Version int `bun:"version,default:0"`
+ Host string `bun:"host"`
+ Port int `bun:"port"`
+ Protocol string `bun:"protocol"`
+ UserName string `bun:"user_name"`
+ Password string `bun:"password"`
+ StartTLS bool `bun:"start_tls"`
+}
+
+type MailAccountDTO struct {
+ ID string `json:"id" binding:"required"`
+ CreatedAt helpers.KontorTime `json:"created_date"`
+ UpdatedAt helpers.KontorTime `json:"last_modified_date"`
+ DeletedAt *time.Time `json:"deleted_date,omitempty"`
+ Version int `json:"version"`
+ Host string `json:"host"`
+ Port int `json:"port"`
+ Protocol string `json:"protocol"`
+ UserName string `json:"user_name"`
+ Password string `json:"password"`
+ StartTLS bool `json:"start_tls"`
+}
+
+func (dto MailAccountDTO) ConvertDTOToModel() MailAccount {
+ model := MailAccount{
+ ID: dto.ID,
+ CreatedAt: dto.CreatedAt.Time,
+ UpdatedAt: dto.UpdatedAt.Time,
+ DeletedAt: dto.DeletedAt,
+ Version: dto.Version,
+ Host: dto.Host,
+ Port: dto.Port,
+ Protocol: dto.Protocol,
+ UserName: dto.UserName,
+ Password: dto.Password,
+ StartTLS: dto.StartTLS,
+ }
+ return model
+}
+
+func ConvertMailAccountsToDtos(mailaccounts []MailAccount) []MailAccountDTO {
+ dtos := make([]MailAccountDTO, len(mailaccounts))
+ for i, mailaccount := range mailaccounts {
+ dtos[i] = MailAccountDTO{
+ ID: mailaccount.ID,
+ CreatedAt: helpers.KontorTime{Time: mailaccount.CreatedAt},
+ UpdatedAt: helpers.KontorTime{Time: mailaccount.UpdatedAt},
+ DeletedAt: mailaccount.DeletedAt,
+ Version: mailaccount.Version,
+ Host: mailaccount.Host,
+ Port: mailaccount.Port,
+ Protocol: mailaccount.Protocol,
+ UserName: mailaccount.UserName,
+ Password: mailaccount.Password,
+ StartTLS: mailaccount.StartTLS,
+ }
+ }
+ return dtos
+}
+
+type MailAccountDTOList []MailAccountDTO
diff --git a/kontor-echo/internal/repository/assignment.go b/kontor-echo/internal/repository/assignment.go
index 487d894..74090bf 100644
--- a/kontor-echo/internal/repository/assignment.go
+++ b/kontor-echo/internal/repository/assignment.go
@@ -4,7 +4,9 @@ import (
"context"
"kontor-api-echo/internal/models"
"log/slog"
+ "time"
+ "github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,41 +21,48 @@ func NewAssignmentRepository(db *bun.DB) *AssignmentRepository {
func (repository *AssignmentRepository) FindAll(context context.Context) ([]models.Assignment, error) {
var assignments []models.Assignment
-
- result := repository.db.Find(&assignments)
- slog.Info("AssignmentRepository#FindAll", "count", result.RowsAffected)
+ err := repository.db.NewSelect().Model(&assignments).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("AssignmentRepository#FindAll", "count", len(assignments))
return assignments, nil
}
-func (repository *AssignmentRepository) GetById(context context.Context, id string) (models.Assignment, error) {
+func (repository *AssignmentRepository) GetById(context context.Context, id string) (*models.Assignment, error) {
var assignment = models.Assignment{ID: id}
slog.Info("AssignmentRepository#GetById", "id", id)
- result := repository.db.First(&assignment)
- if result.Error != nil {
- slog.Info("AssignmentRepository#GetById", "error", result.Error.Error())
+ err := repository.db.NewSelect().Model(&assignment).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
}
- return assignment, result.Error
+ return &assignment, err
}
-func (repository *AssignmentRepository) Import(assignments models.AssignmentDTOList) {
+func (repository *AssignmentRepository) Import(dtos models.AssignmentDTOList) {
slog.Info("AssignmentRepository#Import")
- for index, assignment := range assignments {
- slog.Info("importing", "index", index, "profile", assignment)
- model := assignment.ConvertDTOToModel()
- existing_item := models.Assignment{ID: assignment.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ for index, dto := range dtos {
+ slog.Info("importing", "index", index, "assignment", dto)
+ model := dto.ConvertDTOToModel()
+ existing_item := models.Assignment{ID: dto.ID}
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
diff --git a/kontor-echo/internal/repository/mail.go b/kontor-echo/internal/repository/mail.go
new file mode 100644
index 0000000..1419c0c
--- /dev/null
+++ b/kontor-echo/internal/repository/mail.go
@@ -0,0 +1,70 @@
+package repository
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "log/slog"
+ "time"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type MailRepository struct {
+ db *bun.DB
+}
+
+func NewMailRepository(db *bun.DB) *MailRepository {
+ repository := &MailRepository{db: db}
+ return repository
+}
+
+func (repository *MailRepository) FindAll(context context.Context) ([]models.Mail, error) {
+ var models []models.Mail
+
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
+
+ return models, nil
+}
+
+func (repository *MailRepository) GetById(context context.Context, id string) (*models.Mail, error) {
+ var model = models.Mail{ID: id}
+ slog.Info("MailRepository#GetById", "id", id)
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
+ }
+ return &model, err
+}
+
+func (repository *MailRepository) Import(dtos models.MailDTOList) {
+ slog.Info("MailRepository#Import")
+ for index, dto := range dtos {
+ slog.Info("importing", "index", index, "profile", dto)
+ model := dto.ConvertDTOToModel()
+ existing_item := models.Mail{ID: dto.ID}
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
+ slog.Info("check existing id: not found - inserting")
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
+ }
+ } else {
+ slog.Info("check existing id: found - updating")
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
+ }
+ }
+ }
+}
diff --git a/kontor-echo/internal/repository/mailaccount.go b/kontor-echo/internal/repository/mailaccount.go
new file mode 100644
index 0000000..14d6d00
--- /dev/null
+++ b/kontor-echo/internal/repository/mailaccount.go
@@ -0,0 +1,70 @@
+package repository
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "log/slog"
+ "time"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type MailAccountRepository struct {
+ db *bun.DB
+}
+
+func (repository *MailAccountRepository) Import(dtos models.MailAccountDTOList) {
+ slog.Info("MailAccountRepository#Import")
+ for index, dto := range dtos {
+ slog.Info("importing", "index", index, "mailaccount", dto)
+ model := dto.ConvertDTOToModel()
+ existing_item := models.MailAccount{ID: dto.ID}
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
+ slog.Info("check existing id: not found - inserting")
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
+ }
+ } else {
+ slog.Info("check existing id: found - updating")
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
+ }
+ }
+ }
+}
+
+func NewMailAccountRepository(db *bun.DB) *MailAccountRepository {
+ repository := &MailAccountRepository{db: db}
+ return repository
+}
+
+func (repository *MailAccountRepository) FindAll(context context.Context) ([]models.MailAccount, error) {
+ var models []models.MailAccount
+
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
+
+ return models, nil
+}
+
+func (repository *MailAccountRepository) GetById(context context.Context, id string) (*models.MailAccount, error) {
+ var model = models.MailAccount{ID: id}
+ slog.Info("MailAccountRepository#GetById", "id", id)
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
+ }
+ return &model, err
+}
diff --git a/kontor-echo/internal/repository/media_actor.go b/kontor-echo/internal/repository/media_actor.go
index 4284902..6fe4110 100644
--- a/kontor-echo/internal/repository/media_actor.go
+++ b/kontor-echo/internal/repository/media_actor.go
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
+ "time"
+ "github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaActorRepository) Import(dtos models.MediaActorDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaActor{ID: dto.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,22 +47,27 @@ func NewMediaActorRepository(db *bun.DB) *MediaActorRepository {
}
func (repository *MediaActorRepository) FindAll(context context.Context) ([]models.MediaActor, error) {
- var actors []models.MediaActor
+ var models []models.MediaActor
- result := repository.db.Find(&actors)
- slog.Info("MediaActorRepository#FindAll", "count", result.RowsAffected)
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
- return actors, nil
+ return models, nil
}
func (repository *MediaActorRepository) GetById(context context.Context, id string) (*models.MediaActor, error) {
- var actor = models.MediaActor{ID: id}
+ var model = models.MediaActor{ID: id}
slog.Info("MediaActorRepository#GetById", "id", id)
- result := repository.db.First(&actor)
- if result.Error != nil {
- slog.Info("SportRepository#GetById", "error", result.Error.Error())
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
}
- return &actor, result.Error
+ return &model, err
}
func (repository *MediaActorRepository) Add(context context.Context, url string) (*models.MediaActor, error) {
diff --git a/kontor-echo/internal/repository/media_actor_file.go b/kontor-echo/internal/repository/media_actor_file.go
index 986d36a..2a582d4 100644
--- a/kontor-echo/internal/repository/media_actor_file.go
+++ b/kontor-echo/internal/repository/media_actor_file.go
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
+ "time"
+ "github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaActorFileRepository) Import(dtos models.MediaActorFileDTO
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaActorFile{ID: dto.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,23 +47,27 @@ func NewMediaActorFileRepository(db *bun.DB) *MediaActorFileRepository {
}
func (repository *MediaActorFileRepository) FindAll(context context.Context) ([]models.MediaActorFile, error) {
- var actor_files []models.MediaActorFile
+ var models []models.MediaActorFile
- result := repository.db.Find(&actor_files)
- slog.Info("MediaActorFileRepository#FindAll", "count", result.RowsAffected)
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
- return actor_files, nil
+ return models, nil
}
func (repository *MediaActorFileRepository) GetById(context context.Context, id string) (*models.MediaActorFile, error) {
- var actorfile = models.MediaActorFile{ID: id}
+ var model = models.MediaActorFile{ID: id}
slog.Info("MediaActorFileRepository#GetById", "id", id)
- result := repository.db.First(&actorfile)
- if result.Error != nil {
- slog.Info("MediaActorFileRepository#GetById", "error", result.Error.Error())
- return nil, result.Error
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
}
- return &actorfile, result.Error
+ return &model, err
}
func (repository *MediaActorFileRepository) Add(context context.Context, media_actor_id, media_file_id string) (*models.MediaActorFile, error) {
diff --git a/kontor-echo/internal/repository/media_file.go b/kontor-echo/internal/repository/media_file.go
index 08c9551..d93668c 100644
--- a/kontor-echo/internal/repository/media_file.go
+++ b/kontor-echo/internal/repository/media_file.go
@@ -5,7 +5,9 @@ import (
"fmt"
"kontor-api-echo/internal/models"
"log/slog"
+ "time"
+ "github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -19,18 +21,21 @@ func (repository *MediaFileRepository) Import(dtos models.MediaFileDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaFile{ID: dto.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -42,23 +47,27 @@ func NewMediaFileRepository(db *bun.DB) *MediaFileRepository {
}
func (repository *MediaFileRepository) FindAll(context context.Context) ([]models.MediaFile, error) {
- var files []models.MediaFile
+ var models []models.MediaFile
- result := repository.db.Find(&files)
- slog.Info("MediaFileRepository#FindAll", "count", result.RowsAffected)
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
- return files, nil
+ return models, nil
}
func (repository *MediaFileRepository) GetById(context context.Context, id string) (*models.MediaFile, error) {
- var file = models.MediaFile{ID: id}
+ var model = models.MediaFile{ID: id}
slog.Info("MediaFileRepository#GetById", "id", id)
- result := repository.db.First(&file)
- if result.Error != nil {
- slog.Info("MediaFileRepository#GetById", "error", result.Error.Error())
- return nil, result.Error
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
}
- return &file, result.Error
+ return &model, err
}
func (repository *MediaFileRepository) Add(context context.Context, url string) (*models.MediaFile, error) {
diff --git a/kontor-echo/internal/repository/media_lofi.go b/kontor-echo/internal/repository/media_lofi.go
index c07584d..20d4ab6 100644
--- a/kontor-echo/internal/repository/media_lofi.go
+++ b/kontor-echo/internal/repository/media_lofi.go
@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"errors"
- "fmt"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
@@ -25,18 +24,21 @@ func (repository *MediaLoFiRepository) Import(dtos models.MediaLoFiDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaLoFi{ID: dto.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -48,41 +50,37 @@ func NewMediaLoFiRepository(db *bun.DB) *MediaLoFiRepository {
}
func (repository *MediaLoFiRepository) FindAll(context context.Context) ([]models.MediaLoFi, error) {
- var lofis []models.MediaLoFi
+ var models []models.MediaLoFi
- err := repository.db.NewSelect().Model(&lofis).Scan(context)
+ err := repository.db.NewSelect().Model(&models).Scan(context)
if err != nil {
slog.Info(err.Error())
return nil, echo.ErrInternalServerError
}
- slog.Info("MediaLoFiRepository#FindAll", "count", len(lofis))
+ slog.Info("MailRepository#FindAll", "count", len(models))
- return lofis, nil
+ return models, nil
}
func (repository *MediaLoFiRepository) GetById(context context.Context, id string) (*models.MediaLoFi, error) {
- var lofi = models.MediaLoFi{ID: id}
+ var model = models.MediaLoFi{ID: id}
slog.Info("MediaLoFiRepository#GetById", "id", id)
- err := repository.db.NewSelect().Model(&lofi).Where("id = ?", id).Scan(context)
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
if err != nil {
- slog.Info("MediaLoFiRepository#GetById", "error", err.Error())
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
return nil, err
}
- return &lofi, err
+ return &model, err
}
func (repository *MediaLoFiRepository) Add(context context.Context, url string) (*models.MediaLoFi, error) {
slog.Info("MediaLoFiRepository#Add", "url", url)
webLink := helpers.StripUrl(url, "v")
- var lofi models.MediaLoFi
- search_result := repository.db.Where("url = ?", webLink).First(&lofi)
- if search_result.RowsAffected > 0 {
- slog.Info("search for existing url", "result", search_result, "lofi", lofi)
- return &lofi, nil
- }
- if errors.Is(search_result.Error, sql.ErrNoRows) {
+ var model models.MediaLoFi
+ err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
+ if errors.Is(err, sql.ErrNoRows) {
slog.Info("MediaLoFiRepository#Add URL not found", "url", webLink)
- lofi = models.MediaLoFi{
+ lofi := models.MediaLoFi{
ID: uuid.NewString(),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -94,32 +92,32 @@ func (repository *MediaLoFiRepository) Add(context context.Context, url string)
Title: "",
FileName: "",
}
- add_result := repository.db.Create(&lofi)
- if add_result.Error != nil {
- slog.Info("add new MediaLofi", "error", add_result.Error)
- return nil, add_result.Error
+ _, add_error := repository.db.NewInsert().Model(&model).Exec(context)
+ if add_error != nil {
+ slog.Info("add new MediaLofi", "error", add_error)
+ return nil, add_error
}
slog.Info("add new MediaLofi", "lofi", lofi)
return &lofi, nil
+ } else {
+ slog.Info("search for existing url", "lofi", model)
+ return &model, nil
}
- if search_result.Error != nil {
- return nil, search_result.Error
- }
- return nil, fmt.Errorf("MediaLoFiRepository#Add unknown error")
}
func (repository *MediaLoFiRepository) Update(context context.Context, update models.MediaLoFiDTO) (*models.MediaLoFi, error) {
slog.Info("MediaLoFiRepository#Update", "lofi", update)
- var lofi = models.MediaLoFi{ID: update.ID}
+ var model = models.MediaLoFi{ID: update.ID}
+ model.Update(update)
slog.Info("MediaLoFiRepository#Update", "id", update.ID)
- result := repository.db.First(&lofi)
- if result.Error != nil {
- slog.Info("MediaLoFiRepository#Update", "error", result.Error.Error())
- return nil, result.Error
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", update.ID).
+ Exec(context)
+ if err != nil {
+ slog.Info("MediaLoFiRepository#Update", "error", err.Error())
}
- lofi.Update(update)
- repository.db.Save(&lofi)
- return &lofi, nil
+ return &model, nil
}
func (repository *MediaLoFiRepository) Delete(context context.Context, id string) error {
diff --git a/kontor-echo/internal/repository/media_music.go b/kontor-echo/internal/repository/media_music.go
index b082a63..fb04fdd 100644
--- a/kontor-echo/internal/repository/media_music.go
+++ b/kontor-echo/internal/repository/media_music.go
@@ -4,13 +4,13 @@ import (
"context"
"database/sql"
"errors"
- "fmt"
"kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
"time"
"github.com/google/uuid"
+ "github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -24,18 +24,21 @@ func (repository *MediaMusicRepository) Import(dtos models.MediaMusicDTOList) {
slog.Info("importing", "index", index, "video", dto)
model := dto.ConvertDTOToModel()
existing_item := models.MediaMusic{ID: dto.ID}
- result_existing := repository.db.First(&existing_item)
- if result_existing.Error != nil {
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
slog.Info("check existing id: not found - inserting")
- result := repository.db.Create(&model)
- if result.Error != nil {
- slog.Info("error during import", "error", result.Error.Error())
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
}
} else {
slog.Info("check existing id: found - updating")
- result := repository.db.Save(&model)
- if result.Error != nil {
- slog.Info("error during updating", "error", result.Error.Error())
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
}
}
}
@@ -47,36 +50,37 @@ func NewMediaMusicRepository(db *bun.DB) *MediaMusicRepository {
}
func (repository *MediaMusicRepository) FindAll(context context.Context) ([]models.MediaMusic, error) {
- var musics []models.MediaMusic
+ var models []models.MediaMusic
- result := repository.db.Find(&musics)
- slog.Info("MediaMusicRepository#FindAll", "count", result.RowsAffected)
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
- return musics, nil
+ return models, nil
}
func (repository *MediaMusicRepository) GetById(context context.Context, id string) (*models.MediaMusic, error) {
- var music = models.MediaMusic{ID: id}
+ var model = models.MediaMusic{ID: id}
slog.Info("MediaMusicRepository#GetById", "id", id)
- result := repository.db.First(&music)
- if result.Error != nil {
- slog.Info("MediaMusicRepository#GetById", "error", result.Error.Error())
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
}
- return &music, result.Error
+ return &model, err
}
func (repository *MediaMusicRepository) Add(context context.Context, url string) (*models.MediaMusic, error) {
slog.Info("MediaMusicRepository#Add", "url", url)
webLink := helpers.StripUrl(url, "v")
- var music models.MediaMusic
- search_result := repository.db.Where("url = ?", webLink).First(&music)
- if search_result.RowsAffected > 0 {
- slog.Info("search for existing url", "result", search_result, "music", music)
- return &music, nil
- }
- if errors.Is(search_result.Error, sql.ErrNoRows) {
+ var model models.MediaMusic
+ err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
+ if errors.Is(err, sql.ErrNoRows) {
slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
- music = models.MediaMusic{
+ music := models.MediaMusic{
ID: uuid.NewString(),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -88,32 +92,32 @@ func (repository *MediaMusicRepository) Add(context context.Context, url string)
Title: "",
FileName: "",
}
- add_result := repository.db.Create(&music)
- if add_result.Error != nil {
- slog.Info("add new MediaMusic", "error", add_result.Error)
- return nil, add_result.Error
+ _, add_error := repository.db.NewInsert().Model(&model).Exec(context)
+ if add_error != nil {
+ slog.Info("add new MediaMusic", "error", add_error)
+ return nil, add_error
}
- slog.Info("add new MediaMusic", "music", music)
+ slog.Info("add new MediaMusic", "lofi", music)
return &music, nil
+ } else {
+ slog.Info("search for existing url", "lofi", model)
+ return &model, nil
}
- if search_result.Error != nil {
- return nil, search_result.Error
- }
- return nil, fmt.Errorf("MediaMusicRepository#Add unknown error")
}
func (repository *MediaMusicRepository) Update(context context.Context, update models.MediaMusicDTO) (*models.MediaMusic, error) {
slog.Info("MediaMusicRepository#Update", "music", update)
- var music = models.MediaMusic{ID: update.ID}
- slog.Info("MediaMusicRepository#Update", "id", update.ID)
- result := repository.db.First(&music)
- if result.Error != nil {
- slog.Info("MediaMusicRepository#Update", "error", result.Error.Error())
- return nil, result.Error
+ var model = models.MediaMusic{ID: update.ID}
+ model.Update(update)
+ slog.Info("MediaLoFiRepository#Update", "id", update.ID)
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", update.ID).
+ Exec(context)
+ if err != nil {
+ slog.Info("MediaLoFiRepository#Update", "error", err.Error())
}
- music.Update(update)
- repository.db.Save(&music)
- return &music, nil
+ return &model, nil
}
func (repository *MediaMusicRepository) Delete(context context.Context, id string) error {
diff --git a/kontor-echo/internal/repository/media_video.go b/kontor-echo/internal/repository/media_video.go
index 74041fa..95df8db 100644
--- a/kontor-echo/internal/repository/media_video.go
+++ b/kontor-echo/internal/repository/media_video.go
@@ -2,10 +2,14 @@ package repository
import (
"context"
+ "database/sql"
+ "errors"
+ "kontor-api-echo/internal/helpers"
"kontor-api-echo/internal/models"
"log/slog"
"time"
+ "github.com/google/uuid"
"github.com/labstack/echo/v5"
"github.com/uptrace/bun"
)
@@ -68,42 +72,37 @@ func (repository *MediaVideoRepository) GetById(context context.Context, id stri
return &video, nil
}
-// func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
-// slog.Info("MediaVideoRepository#Add", "url", url)
-// webLink := helpers.StripUrl(url, "v")
-// var video models.MediaVideo
-// search_result := repository.db.Where("url = ?", webLink).First(&video)
-// if search_result.RowsAffected > 0 {
-// slog.Info("search for existing url", "result", search_result, "video", video)
-// return &video, nil
-// }
-// if errors.Is(search_result.Error, sql.ErrNoRows) {
-// slog.Info("MediaVideoRepository#Add URL not found", "url", webLink)
-// video = models.MediaVideo{
-// ID: uuid.NewString(),
-// CreatedAt: time.Now(),
-// UpdatedAt: time.Now(),
-// DeletedAt: nil,
-// Version: 0,
-// WebLink: webLink,
-// ShouldDownload: false,
-// Review: true,
-// Title: "",
-// FileName: "",
-// }
-// add_result := repository.db.Create(&video)
-// if add_result.Error != nil {
-// slog.Info("add new MediaVideo", "error", add_result.Error)
-// return nil, add_result.Error
-// }
-// slog.Info("add new MediaVideo", "music", video)
-// return &video, nil
-// }
-// if search_result.Error != nil {
-// return nil, search_result.Error
-// }
-// return nil, fmt.Errorf("MediaVideoRepository#Add unknown error")
-// }
+func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
+ slog.Info("MediaVideoRepository#Add", "url", url)
+ webLink := helpers.StripUrl(url, "v")
+ var model models.MediaVideo
+ err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
+ if errors.Is(err, sql.ErrNoRows) {
+ slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
+ video := models.MediaVideo{
+ ID: uuid.NewString(),
+ CreatedAt: time.Now(),
+ UpdatedAt: time.Now(),
+ DeletedAt: nil,
+ Version: 0,
+ WebLink: webLink,
+ ShouldDownload: false,
+ Review: true,
+ Title: "",
+ FileName: "",
+ }
+ _, add_error := repository.db.NewInsert().Model(&model).Exec(context)
+ if add_error != nil {
+ slog.Info("add new MediaMusic", "error", add_error)
+ return nil, add_error
+ }
+ slog.Info("add new MediaMusic", "lofi", video)
+ return &video, nil
+ } else {
+ slog.Info("search for existing url", "lofi", model)
+ return &model, nil
+ }
+}
func (repository *MediaVideoRepository) Update(context context.Context, update models.MediaVideoDTO) (*models.MediaVideo, error) {
slog.Info("MediaVideoRepository#Update", "video", update)
diff --git a/kontor-echo/internal/repository/profile.go b/kontor-echo/internal/repository/profile.go
index d3d498a..7d68260 100644
--- a/kontor-echo/internal/repository/profile.go
+++ b/kontor-echo/internal/repository/profile.go
@@ -31,9 +31,10 @@ func (repository *ProfileRepository) FindAll(context context.Context) ([]models.
return profiles, nil
}
-func (repository *ProfileRepository) FindProfileByEmail(context context.Context, email string) (*models.Profile, error) {
+func (repository *ProfileRepository) FindProfileByEmail(email string) (*models.Profile, error) {
var profile models.Profile
slog.Info("MediaArticleRepository#GetById", "email", email)
+ context := context.Background()
err := repository.db.NewSelect().Model(&profile).Where("email = ?", email).Scan(context)
if err != nil {
diff --git a/kontor-echo/internal/repository/token.go b/kontor-echo/internal/repository/token.go
new file mode 100644
index 0000000..c8b6d93
--- /dev/null
+++ b/kontor-echo/internal/repository/token.go
@@ -0,0 +1,70 @@
+package repository
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "log/slog"
+ "time"
+
+ "github.com/labstack/echo/v5"
+ "github.com/uptrace/bun"
+)
+
+type TokenRepository struct {
+ db *bun.DB
+}
+
+func (repository *TokenRepository) Import(dtos models.TokenDTOList) {
+ slog.Info("TokenRepository#Import")
+ for index, dto := range dtos {
+ slog.Info("importing", "index", index, "video", dto)
+ model := dto.ConvertDTOToModel()
+ existing_item := models.Token{ID: dto.ID}
+ err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
+ if err != nil {
+ slog.Info("check existing id: not found - inserting")
+ _, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
+ if err != nil {
+ slog.Info("error during import", "error", err.Error())
+ }
+ } else {
+ slog.Info("check existing id: found - updating")
+ _, err := repository.db.NewUpdate().Model(&model).
+ Set("updated_at = ? ", time.Now).
+ Where("id = ?", model.ID).
+ Exec(context.Background())
+ if err != nil {
+ slog.Info("error during updating", "error", err.Error())
+ }
+ }
+ }
+}
+
+func NewTokenRepository(db *bun.DB) *TokenRepository {
+ repository := &TokenRepository{db: db}
+ return repository
+}
+
+func (repository *TokenRepository) FindAll(context context.Context) ([]models.Token, error) {
+ var models []models.Token
+
+ err := repository.db.NewSelect().Model(&models).Scan(context)
+ if err != nil {
+ slog.Info(err.Error())
+ return nil, echo.ErrInternalServerError
+ }
+ slog.Info("MailRepository#FindAll", "count", len(models))
+
+ return models, nil
+}
+
+func (repository *TokenRepository) GetById(context context.Context, id string) (*models.Token, error) {
+ var model = models.Token{ID: id}
+ slog.Info("TokenRepository#GetById", "id", id)
+ err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
+ if err != nil {
+ slog.Info("AssignmentRepository#GetById", "error", err.Error())
+ return nil, err
+ }
+ return &model, err
+}
diff --git a/kontor-echo/internal/router/router.go b/kontor-echo/internal/router/router.go
index 82c4568..7f35ce8 100644
--- a/kontor-echo/internal/router/router.go
+++ b/kontor-echo/internal/router/router.go
@@ -1,34 +1,154 @@
package router
import (
+ "html/template"
+ "io"
+ "kontor-api-echo/assets"
+ "kontor-api-echo/internal/config"
"kontor-api-echo/internal/handlers"
+ "kontor-api-echo/templates"
"log/slog"
+ "os"
+ echojwt "github.com/labstack/echo-jwt/v5"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
+type Template struct {
+ templates *template.Template
+}
+
+func (t *Template) Render(c *echo.Context, w io.Writer, name string, data any) error {
+ return t.templates.ExecuteTemplate(w, name, data)
+}
+
func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Echo {
e := echo.New()
- skipper := func(c *echo.Context) bool {
- // Skip health check endpoint
- return c.Request().URL.Path == "/health"
- }
+ logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
+
+ e.Use(middleware.Recover())
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
- LogStatus: true,
LogURI: true,
+ LogStatus: true,
HandleError: true,
- Skipper: skipper,
+ Skipper: func(c *echo.Context) bool {
+ // Skip health check endpoint
+ return c.Path() == "/health"
+ },
LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error {
- if v.Error == nil {
- slog.Info("REQUEST", "uri", v.URI, "status", v.Status)
- } else {
- slog.Info("REQUEST-ERROR", "uri", v.URI, "status", v.Status, "err", v.Error.Error())
+ if v.Error != nil {
+ logger.Error("request failed", "uri", v.URI, "status", v.Status, "error", v.Error)
+ return nil
}
+ logger.Info("request", "uri", v.URI, "status", v.Status)
return nil
},
}))
+
+ e.StaticFS("/public", echo.MustSubFS(assets.StaticFiles, "assets"))
+
+ templ := template.Must(template.New("").ParseFS(templates.TemplateFiles, "layouts/*.html", "pages/*.html"))
+
+ t := &Template{
+ templates: templ,
+ }
+
+ e.Renderer = t
+
+ e.GET("/health", handlers.Health)
+ e.GET("/", handlers.Index)
+ e.GET("/login", admin.AuthHandler.LoginPage)
+ e.POST("/login", admin.AuthHandler.LoginPost)
+ e.GET("/logout", admin.AuthHandler.LogoutPage)
+
+ mediaGroup := e.Group("/media")
+ //mediaGroup.Use(middleware.AuthRequired())
+ mediaGroup.GET("/actors", media.MediaActorHandler.ListPage)
+ mediaGroup.GET("/actors/:id", media.MediaActorHandler.EditPage)
+ mediaGroup.POST("/actors/:id", media.MediaActorHandler.UpdatePage)
+ mediaGroup.GET("/articles", media.MediaArticleHandler.ListPage)
+ mediaGroup.GET("/files", media.MediaFileHandler.ListPage)
+ mediaGroup.GET("/files/edit/:id", media.MediaFileHandler.EditPage)
+ mediaGroup.POST("/files/edit/:id", media.MediaFileHandler.UpdatePage)
+ mediaGroup.GET("/files/delete/:id", media.MediaFileHandler.DeletePage)
+ mediaGroup.GET("/videos", media.MediaVideoHandler.ListPage)
+ mediaGroup.GET("/videos/edit/:id", media.MediaVideoHandler.EditPage)
+ mediaGroup.POST("/videos/edit/:id", media.MediaVideoHandler.UpdatePage)
+ mediaGroup.GET("/videos/delete/:id", media.MediaVideoHandler.DeletePage)
+ mediaGroup.GET("/lofis", media.MediaLoFiHandler.ListPage)
+ mediaGroup.GET("/lofis/edit", media.MediaLoFiHandler.EditPage)
+ mediaGroup.GET("/lofis/edit/:id", media.MediaLoFiHandler.EditPage)
+ mediaGroup.POST("/lofis/edit/:id", media.MediaLoFiHandler.UpdatePage)
+ mediaGroup.GET("/lofis/review/:id", media.MediaLoFiHandler.ChangeReviewPage)
+ mediaGroup.GET("/lofis/delete/:id", media.MediaLoFiHandler.DeletePage)
+ mediaGroup.GET("/musics", media.MediaMusicHandler.ListPage)
+ mediaGroup.GET("/musics/edit/:id", media.MediaMusicHandler.EditPage)
+ mediaGroup.POST("/musics/edit/:id", media.MediaMusicHandler.UpdatePage)
+ mediaGroup.GET("/musics/delete/:id", media.MediaMusicHandler.DeletePage)
+
+ api := e.Group("/api")
+ api.POST("/login", admin.AuthHandler.Login)
+
+ v1 := api.Group("/v1")
+ {
+ secured := v1.Group("")
+ secured.Use(echojwt.WithConfig(echojwt.Config{SigningKey: config.ServerConfig.ApiSecret}))
+ //secured.Use(middleware.JWT(admin.Secret))
+ // secured.GET("admin/mailaccounts", admin.MailAccountHandler.List)
+ // secured.GET("user/profiles", admin.ProfileHandler.List)
+ // secured.GET("user/permissions", admin.PermissionHandler.List)
+ // secured.GET("user/assignments", admin.AssignmentHandler.List)
+ // secured.GET("user/mails", admin.MailHandler.List)
+ // secured.GET("user/tokens", admin.TokenHandler.List)
+ // secured.GET("tysc/sports", tysc.SportHandler.List)
+ // secured.GET("tysc/sports/:id", tysc.SportHandler.Get)
+ // secured.GET("tysc/players", tysc.PlayerHandler.List)
+ // secured.GET("tysc/teams", tysc.TeamHandler.List)
+ // secured.GET("tysc/positions", tysc.PositionHandler.List)
+ // secured.GET("tysc/roosters", tysc.RoosterHandler.List)
+ // secured.GET("tysc/vendors", tysc.VendorHandler.List)
+ // secured.GET("tysc/cardsets", tysc.CardSetHandler.List)
+ // secured.GET("tysc/cards", tysc.CardHandler.List)
+ // secured.GET("bookshelf/articles", bookshelf.ArticleHandler.List)
+ // secured.GET("bookshelf/publishers", bookshelf.BookshelfPublisherHandler.List)
+ // secured.GET("bookshelf/books", bookshelf.BookHandler.List)
+ // secured.GET("bookshelf/authors", bookshelf.AuthorHandler.List)
+ // secured.GET("bookshelf/articleauthors", bookshelf.ArticleAuthorHandler.List)
+ // secured.GET("bookshelf/bookauthors", bookshelf.BookAuthorHandler.List)
+ // secured.GET("comics/comics", comics.ComicHandler.List)
+ // secured.GET("comics/publishers", comics.PublisherHandler.List)
+ // secured.GET("comics/artists", comics.ArtistHandler.List)
+ // secured.GET("comics/issues", comics.IssueHandler.List)
+ // secured.GET("comics/tradepaperbacks", comics.TradePaperbackHandler.List)
+ // secured.GET("comics/worktypes", comics.WorkTypeHandler.List)
+ // secured.GET("comics/volumes", comics.VolumeHandler.List)
+ // secured.GET("comics/storyarcs", comics.StoryArcHandler.List)
+ // secured.GET("comics/comicworks", comics.ComicworkHandler.List)
+ // secured.GET("comics/issueworks", comics.IssueworkHandler.List)
+ mediaGroup := secured.Group("media")
+ mediaGroup.GET("/files", media.MediaFileHandler.List)
+ mediaGroup.POST("/files", media.MediaFileHandler.Add)
+ // mediaGroup.GET("/videos", media.MediaVideoHandler.List)
+ // mediaGroup.GET("/lofis", media.MediaLoFiHandler.List)
+ // mediaGroup.POST("/lofis", media.MediaLoFiHandler.Add)
+ // mediaGroup.GET("/lofis/:id", media.MediaLoFiHandler.Get)
+ // mediaGroup.POST("/lofis/:id", media.MediaLoFiHandler.Update)
+ // mediaGroup.DELETE("/lofis/:id", media.MediaLoFiHandler.Delete)
+ // mediaGroup.POST("/musics", media.MediaMusicHandler.Add)
+ // mediaGroup.GET("/musics/:id", media.MediaMusicHandler.Get)
+ // mediaGroup.POST("/musics/:id", media.MediaMusicHandler.Update)
+ // mediaGroup.DELETE("/musics/:id", media.MediaMusicHandler.Delete)
+ // mediaGroup.GET("/actors", media.MediaActorHandler.List)
+ // mediaGroup.POST("/actors", media.MediaActorHandler.Add)
+ // mediaGroup.GET("/actors/:id", media.MediaActorHandler.Get)
+ // mediaGroup.DELETE("/actors/:id", media.MediaActorHandler.Delete)
+ // mediaGroup.GET("/actorfiles", media.MediaActorFileHandler.List)
+ // mediaGroup.POST("/actorfiles", media.MediaActorFileHandler.Add)
+ // mediaGroup.DELETE("/actorfiles", media.MediaActorFileHandler.Delete)
+ }
+
return e
}
diff --git a/kontor-echo/internal/service/assignment.go b/kontor-echo/internal/service/assignment.go
index dc7dc92..40d923d 100644
--- a/kontor-echo/internal/service/assignment.go
+++ b/kontor-echo/internal/service/assignment.go
@@ -21,7 +21,7 @@ func (service *AssignmentService) List(context context.Context) ([]models.Assign
return service.repository.FindAll(context)
}
-func (service *AssignmentService) Get(context context.Context, id string) (models.Assignment, error) {
+func (service *AssignmentService) Get(context context.Context, id string) (*models.Assignment, error) {
slog.Info("AssignmentService#Get")
return service.repository.GetById(context, id)
}
diff --git a/kontor-echo/internal/service/auth.go b/kontor-echo/internal/service/auth.go
new file mode 100644
index 0000000..3ba1038
--- /dev/null
+++ b/kontor-echo/internal/service/auth.go
@@ -0,0 +1,47 @@
+package service
+
+import (
+ "kontor-api-echo/internal/helpers"
+ "kontor-api-echo/internal/repository"
+
+ "golang.org/x/crypto/bcrypt"
+)
+
+type AuthService struct {
+ repository *repository.ProfileRepository
+}
+
+func NewAuthService(repository *repository.ProfileRepository) *AuthService {
+ service := &AuthService{repository: repository}
+ return service
+}
+
+func VerifyPassword(password, hashedPassword string) error {
+ return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
+}
+
+func (service *AuthService) LoginCheck(email string, password string) (string, error) {
+
+ var err error
+
+ profile, err := service.repository.FindProfileByEmail(email)
+
+ if err != nil {
+ return "", err
+ }
+
+ err = VerifyPassword(password, profile.Password)
+
+ if err != nil && err == bcrypt.ErrMismatchedHashAndPassword {
+ return "", err
+ }
+
+ token, err := helpers.GenerateToken(profile.ID)
+
+ if err != nil {
+ return "", err
+ }
+
+ return token, nil
+
+}
diff --git a/kontor-echo/internal/service/mail.go b/kontor-echo/internal/service/mail.go
new file mode 100644
index 0000000..4f64a70
--- /dev/null
+++ b/kontor-echo/internal/service/mail.go
@@ -0,0 +1,27 @@
+package service
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "log/slog"
+)
+
+type MailService struct {
+ repository *repository.MailRepository
+}
+
+func NewMailService(repo *repository.MailRepository) *MailService {
+ service := &MailService{repository: repo}
+ return service
+}
+
+func (service *MailService) List(context context.Context) ([]models.Mail, error) {
+ slog.Info("MailService#List")
+ return service.repository.FindAll(context)
+}
+
+func (service *MailService) Get(context context.Context, id string) (*models.Mail, error) {
+ slog.Info("MailService#Get")
+ return service.repository.GetById(context, id)
+}
diff --git a/kontor-echo/internal/service/mailaccount.go b/kontor-echo/internal/service/mailaccount.go
new file mode 100644
index 0000000..791200c
--- /dev/null
+++ b/kontor-echo/internal/service/mailaccount.go
@@ -0,0 +1,27 @@
+package service
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "log/slog"
+)
+
+type MailAccountService struct {
+ repository *repository.MailAccountRepository
+}
+
+func NewMailAccountService(repo *repository.MailAccountRepository) *MailAccountService {
+ service := &MailAccountService{repository: repo}
+ return service
+}
+
+func (service *MailAccountService) List(context context.Context) ([]models.MailAccount, error) {
+ slog.Info("MailAccountService#List")
+ return service.repository.FindAll(context)
+}
+
+func (service *MailAccountService) Get(context context.Context, id string) (*models.MailAccount, error) {
+ slog.Info("MailAccountService#Get")
+ return service.repository.GetById(context, id)
+}
diff --git a/kontor-echo/internal/service/token.go b/kontor-echo/internal/service/token.go
new file mode 100644
index 0000000..64123f1
--- /dev/null
+++ b/kontor-echo/internal/service/token.go
@@ -0,0 +1,27 @@
+package service
+
+import (
+ "context"
+ "kontor-api-echo/internal/models"
+ "kontor-api-echo/internal/repository"
+ "log/slog"
+)
+
+type TokenService struct {
+ repository *repository.TokenRepository
+}
+
+func NewTokenService(repo *repository.TokenRepository) *TokenService {
+ service := &TokenService{repository: repo}
+ return service
+}
+
+func (service *TokenService) List(context context.Context) ([]models.Token, error) {
+ slog.Info("TokenService#List")
+ return service.repository.FindAll(context)
+}
+
+func (service *TokenService) Get(context context.Context, id string) (*models.Token, error) {
+ slog.Info("TokenService#Get")
+ return service.repository.GetById(context, id)
+}
diff --git a/kontor-echo/pkg/handler/health.go b/kontor-echo/pkg/handler/health.go
deleted file mode 100644
index d97ce24..0000000
--- a/kontor-echo/pkg/handler/health.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package handler
-
-import (
- "net/http"
-
- "github.com/labstack/echo/v4"
-)
-
-type Status struct {
- Status string `json:"status"`
-}
-
-func GetHealth(c echo.Context) error {
- status := new(Status)
- status.Status = "ok"
- return c.JSON(http.StatusOK, status)
-}
diff --git a/kontor-echo/pkg/handler/media.go b/kontor-echo/pkg/handler/media.go
deleted file mode 100644
index 46e7eba..0000000
--- a/kontor-echo/pkg/handler/media.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package handler
-
-import (
- "context"
- "fmt"
- "kontor-api-echo/pkg/schema"
- "log"
- "net/http"
- "time"
-
- "github.com/google/uuid"
- "github.com/labstack/echo/v4"
- "github.com/uptrace/bun"
-)
-
-func SetupMediaRoutes(api *echo.Group) {
- media := api.Group("/media")
- media.GET("/files", GetAllFiles)
- media.POST("/files", AddFile)
-}
-
-func GetAllFiles(c echo.Context) error {
- var files []schema.MediaFile
- var err error
- var db *bun.DB
- ctx := context.Background()
-
- db, err = schema.GetDatabase()
- if err != nil {
- log.Fatal(err)
- }
- err = db.NewSelect().Model(&files).Relation("MediaActorFiles").Scan(ctx)
- if err != nil {
- log.Fatal(err)
- return echo.ErrInternalServerError
- }
-
- return c.JSON(http.StatusOK, files)
-}
-
-type Link struct {
- URL string `json:"url"`
-}
-
-func AddFile(c echo.Context) error {
- var err error
- var db *bun.DB
- ctx := context.Background()
- link := new(Link)
- if err = c.Bind(link); err != nil {
- return err
- }
- log.Printf("URL %s has been sent", link)
-
- db, err = schema.GetDatabase()
- if err != nil {
- log.Fatal(err)
- }
- id := uuid.NewString()
- timestamp := time.Now()
- mediafile := &schema.MediaFile{ID: id, CreatedAt: timestamp, UpdatedAt: timestamp, WebLink: fmt.Sprintf("%s", link), Version: 1, ShouldDownload: true, Review: true}
- _, err = db.NewInsert().Model(mediafile).Exec(ctx)
- if err != nil {
- return err
- }
- return c.String(http.StatusCreated, "Link created")
-}
diff --git a/kontor-echo/templates/layouts/footer.html b/kontor-echo/templates/layouts/footer.html
new file mode 100644
index 0000000..8d9d7f2
--- /dev/null
+++ b/kontor-echo/templates/layouts/footer.html
@@ -0,0 +1,9 @@
+{{ define "footer" }}
+
+
+
+{{ end }}
diff --git a/kontor-echo/templates/layouts/head.html b/kontor-echo/templates/layouts/head.html
new file mode 100644
index 0000000..6aacaa5
--- /dev/null
+++ b/kontor-echo/templates/layouts/head.html
@@ -0,0 +1,13 @@
+{{ define "head" }}
+
+
+
+
+
+
+
+
+
+ {{ .title }}
+
+{{ end }}
diff --git a/kontor-echo/templates/layouts/main.html b/kontor-echo/templates/layouts/main.html
new file mode 100644
index 0000000..2235cf5
--- /dev/null
+++ b/kontor-echo/templates/layouts/main.html
@@ -0,0 +1,24 @@
+{{ define "main" }}
+
+
+
+
+
+
+
+ {{ .title }}
+
+
+
+
+ {{ template "navbar" . }}
+ {{ template "content" . }}
+
+
+
+{{ end }}
diff --git a/kontor-echo/templates/layouts/navbar.html b/kontor-echo/templates/layouts/navbar.html
new file mode 100644
index 0000000..bc15f62
--- /dev/null
+++ b/kontor-echo/templates/layouts/navbar.html
@@ -0,0 +1,88 @@
+{{ define "navbar" }}
+
+
+
+
+
+
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/comics.html b/kontor-echo/templates/pages/comics.html
new file mode 100644
index 0000000..40b5ad4
--- /dev/null
+++ b/kontor-echo/templates/pages/comics.html
@@ -0,0 +1,59 @@
+{{ define "comics" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+
+
+ | Title |
+ Publisher |
+ Completed |
+ Actions |
+
+
+
+ {{ range .comics }}
+
+ | {{.Title}} |
+ {{ if .Publisher }}
+ {{.Publisher.Name}} |
+ {{ else }}
+ Publisher not set |
+ {{ end }}
+
+ {{ if .Completed }}
+
+ {{ else }}
+
+ {{ end }}
+ |
+ Edit |
+ Delete |
+
+ {{ end }}
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/home.html b/kontor-echo/templates/pages/home.html
new file mode 100644
index 0000000..efef156
--- /dev/null
+++ b/kontor-echo/templates/pages/home.html
@@ -0,0 +1,27 @@
+{{ define "home" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+
Hauptinhalt
+
{{ .message }}
+
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/lofi.html b/kontor-echo/templates/pages/lofi.html
new file mode 100644
index 0000000..30d0d5d
--- /dev/null
+++ b/kontor-echo/templates/pages/lofi.html
@@ -0,0 +1,69 @@
+{{ define "lofi" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
Media Lofi
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+
+
+
+ | Title |
+ Weblink |
+ Review |
+ Actions |
+
+
+ {{ range .lofis }}
+
+ | {{.Title}} |
+ {{ if .WebLink }}
+ {{.WebLink}} |
+ {{ else }}
+ WebLink not set |
+ {{ end }}
+
+ {{ if .Review }}
+
+ {{ else }}
+
+ {{ end }}
+ |
+ Edit |
+ Delete |
+
+ {{ end }}
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/lofi_detail.html b/kontor-echo/templates/pages/lofi_detail.html
new file mode 100644
index 0000000..717509b
--- /dev/null
+++ b/kontor-echo/templates/pages/lofi_detail.html
@@ -0,0 +1,54 @@
+{{ define "lofi_detail" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
Media Lofi
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+ {{ if .Errors }}
+
{{ .Errors }}
+ {{ end }}
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/login.html b/kontor-echo/templates/pages/login.html
new file mode 100644
index 0000000..b0a9cc2
--- /dev/null
+++ b/kontor-echo/templates/pages/login.html
@@ -0,0 +1,36 @@
+{{ define "login" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/media_actor.html b/kontor-echo/templates/pages/media_actor.html
new file mode 100644
index 0000000..7f3001a
--- /dev/null
+++ b/kontor-echo/templates/pages/media_actor.html
@@ -0,0 +1,54 @@
+{{ define "actor_detail" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
Media Actor
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+ {{ if .Errors }}
+
{{ .Errors }}
+ {{ end }}
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/media_actors.html b/kontor-echo/templates/pages/media_actors.html
new file mode 100644
index 0000000..79e992c
--- /dev/null
+++ b/kontor-echo/templates/pages/media_actors.html
@@ -0,0 +1,41 @@
+{{ define "media_actors" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
Media Actors
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+
+ {{ range .actors }}
+
+
+
{{.Name}}
+
Read more
+
+
+ {{ end }}
+
+
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/media_detail.html b/kontor-echo/templates/pages/media_detail.html
new file mode 100644
index 0000000..293e7ff
--- /dev/null
+++ b/kontor-echo/templates/pages/media_detail.html
@@ -0,0 +1,54 @@
+{{ define "media_detail" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
{{.message}}
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+ {{ if .Errors }}
+
{{ .Errors }}
+ {{ end }}
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/media_links.html b/kontor-echo/templates/pages/media_links.html
new file mode 100644
index 0000000..4dad134
--- /dev/null
+++ b/kontor-echo/templates/pages/media_links.html
@@ -0,0 +1,71 @@
+{{ define "media_links" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/mediafiles.html b/kontor-echo/templates/pages/mediafiles.html
new file mode 100644
index 0000000..59bcbed
--- /dev/null
+++ b/kontor-echo/templates/pages/mediafiles.html
@@ -0,0 +1,71 @@
+{{ define "mediafiles" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/mediavideos.html b/kontor-echo/templates/pages/mediavideos.html
new file mode 100644
index 0000000..88ce5e8
--- /dev/null
+++ b/kontor-echo/templates/pages/mediavideos.html
@@ -0,0 +1,71 @@
+{{ define "mediavideos" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/pages/publishers.html b/kontor-echo/templates/pages/publishers.html
new file mode 100644
index 0000000..cd1e982
--- /dev/null
+++ b/kontor-echo/templates/pages/publishers.html
@@ -0,0 +1,42 @@
+{{ define "publishers" }}
+
+
+ {{ template "head" . }}
+
+
+ {{ template "navbar" . }}
+
+
+
+
Comic Publishers
+
Hier steht der wesentliche Inhalt der Seite.
+
+
+
+
+
+ {{ range .publishers }}
+
+
+
{{.Name}}
+
Read more
+
+
+ {{ end }}
+
+
+ {{ template "footer" . }}
+
+
+{{ end }}
diff --git a/kontor-echo/templates/templates.go b/kontor-echo/templates/templates.go
new file mode 100644
index 0000000..f3737ba
--- /dev/null
+++ b/kontor-echo/templates/templates.go
@@ -0,0 +1,8 @@
+package templates
+
+import (
+ "embed"
+)
+
+//go:embed layouts/* pages/*
+var TemplateFiles embed.FS