diff --git a/kontor-echo/cmd/kontor-echo/main.go b/kontor-echo/cmd/kontor-echo/main.go index 46f4c2c..fa9084c 100644 --- a/kontor-echo/cmd/kontor-echo/main.go +++ b/kontor-echo/cmd/kontor-echo/main.go @@ -1,39 +1,42 @@ package main import ( - "context" - "net/http" - "os" - "os/signal" - "syscall" - "time" + "context" + "kontor-api-echo/internal/config" + "kontor-api-echo/internal/handlers" + "kontor-api-echo/internal/router" + "kontor-api-echo/pkg/schema" "log" "log/slog" - echojwt "github.com/labstack/echo-jwt/v4" - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" + "os" + "os/signal" + "syscall" + "time" + + "github.com/labstack/echo/v5" ) + func main() { slog.Info("Kontor started") - db, err := schema.GetDatabase() + db, _ := schema.GetDatabase() if err := config.InitConfig(); err != nil { log.Fatalf("Failed to initialize config: %v", err) } e := router.New(handlers.NewAdminHandler(db, config.ServerConfig.ApiSecret), handlers.NewMediaHandler(db)) - // Cancel the context on SIGINT / SIGTERM - ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) - defer stop() + // Cancel the context on SIGINT / SIGTERM + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() - sc := echo.StartConfig{ - Address: ":1323", - GracefulTimeout: 10 * time.Second, - } - if err := sc.Start(ctx, e); err != nil { - e.Logger.Error("server stopped", "error", err) - } + sc := echo.StartConfig{ + Address: ":1323", + GracefulTimeout: 10 * time.Second, + } + if err := sc.Start(ctx, e); err != nil { + e.Logger.Error("server stopped", "error", err) + } slog.Info("Kontor finished") } diff --git a/kontor-echo/go.mod b/kontor-echo/go.mod index 0ea3573..c295ed8 100644 --- a/kontor-echo/go.mod +++ b/kontor-echo/go.mod @@ -10,31 +10,58 @@ require ( 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.2.16 + github.com/uptrace/bun v1.3.0 github.com/uptrace/bun/dialect/pgdialect v1.2.16 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/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 + golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect + modernc.org/libc v1.68.0 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.46.1 // indirect +) + require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pelletier/go-toml/v2 v2.4.3 // indirect 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/pflag v1.1.0 // indirect + github.com/spf13/viper v1.21.0 // indirect + 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 + github.com/uptrace/bun/driver/sqliteshim v1.3.0 github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opentelemetry.io/otel v1.39.0 // indirect 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.47.0 // indirect - golang.org/x/text v0.40.0 // indirect + golang.org/x/sys v0.49.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 mellium.im/sasl v0.3.2 // indirect diff --git a/kontor-echo/go.sum b/kontor-echo/go.sum index 852b787..f8ba6c2 100644 --- a/kontor-echo/go.sum +++ b/kontor-echo/go.sum @@ -1,13 +1,22 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 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/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= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= 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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -26,22 +35,54 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= +github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY= +github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= 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/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= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.1.0 h1:6W6MbVUrnMb8PEhjkqwsVLY7ryuzRfFHF4mQd7L94ag= +github.com/spf13/pflag v1.1.0/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +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/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= github.com/uptrace/bun/driver/pgdriver v1.2.16/go.mod h1:H6lUZ9CBfp1X5Vq62YGSV7q96/v94ja9AYFjKvdoTk0= +github.com/uptrace/bun/driver/sqliteshim v1.3.0 h1:T3ybxgmP8ejA99YULje9e12h+FqKKAP/4xZo3+X3mXA= +github.com/uptrace/bun/driver/sqliteshim v1.3.0/go.mod h1:MqvqMCAAKNn6M0HF9YK/Z6xrnCP6sih5OZ37AxdAlHw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= @@ -54,15 +95,24 @@ go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.6 h1:zcDfvjXEqTQmpjniUBLc91xYJMB2c4QOFxEF/LCEckM= +go.yaml.in/yaml/v3 v3.0.6/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= 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/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/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/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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -72,3 +122,11 @@ 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/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/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= +modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= diff --git a/kontor-echo/internal/config/config.go b/kontor-echo/internal/config/config.go index 09a92d4..87b0a91 100644 --- a/kontor-echo/internal/config/config.go +++ b/kontor-echo/internal/config/config.go @@ -87,6 +87,7 @@ type ServerConfiguration struct { Gin struct { Mode string `mapstructure:"mode" validate:"required"` } `mapstructure:"gin"` + ApiSecret []byte `mapstructure:"api_secret"` } func InitCliConfig() { diff --git a/kontor-echo/internal/config/database.go b/kontor-echo/internal/config/database.go index 9f10f1c..976e59e 100644 --- a/kontor-echo/internal/config/database.go +++ b/kontor-echo/internal/config/database.go @@ -1,37 +1,31 @@ package config import ( + "database/sql" "fmt" "log/slog" - "gorm.io/driver/postgres" - "gorm.io/driver/sqlite" - "gorm.io/gorm" - "gorm.io/gorm/logger" + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect/pgdialect" + "github.com/uptrace/bun/dialect/sqlitedialect" + "github.com/uptrace/bun/driver/pgdriver" + "github.com/uptrace/bun/driver/sqliteshim" ) -func NewDB(db Database) (*gorm.DB, error) { +func NewDB(db Database) (*bun.DB, error) { db_type := db.Type slog.Info("using database", "type", db_type) switch db_type { case "postgres": - dsn := fmt.Sprintf( - "host=%s user=%s password=%s dbname=%s port=%d sslmode=disable", - db.Host, - db.User, - db.Password, - db.Name, - db.Port, - ) - - return gorm.Open(postgres.Open(dsn), &gorm.Config{ - Logger: logger.Default.LogMode(logger.Info), - }) + dsn := fmt.Sprintf("postgres://%s:%s@%s:%d/%s", db.User, db.Password, db.Host, db.Port, db.Name) + sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn))) + db := bun.NewDB(sqldb, pgdialect.New()) + return db, nil case "sqlite": - return gorm.Open(sqlite.Open(db.Path), &gorm.Config{ - Logger: logger.Default.LogMode(logger.Info), - }) + sqldb, _ := sql.Open(sqliteshim.ShimName, "file::memory:?cache=shared") + db := bun.NewDB(sqldb, sqlitedialect.New()) + return db, nil default: return nil, fmt.Errorf("unknown db.type=%s", db_type) } diff --git a/kontor-echo/internal/globals/globals.go b/kontor-echo/internal/globals/globals.go new file mode 100644 index 0000000..bf4e34b --- /dev/null +++ b/kontor-echo/internal/globals/globals.go @@ -0,0 +1,39 @@ +package globals + +import ( + "fmt" +) + +var ( + Secret = []byte("secret") + + Version = "unset" + Commit = "unset" + Date = "unset" +) + +const ( + UserKey = "user" + MediaFileLink = "/media/files" + MediaLofiLink = "/media/lofis" + MediaMusicLink = "/media/musics" + MediaVideoLink = "/media/videos" + MediaArticleLink = "/media/articles" + MediaActorLink = "/media/actors" +) + +func GetDefaultValues(user interface{}, message string) map[string]any { + values := map[string]any{ + "title": "Kontor", + "version": fmt.Sprintf("%s %s", Version, Commit), + "message": message, + "user": user, + "media_file_link": MediaFileLink, + "media_lofi_link": MediaLofiLink, + "media_music_link": MediaMusicLink, + "media_video_link": MediaVideoLink, + "media_article_link": MediaArticleLink, + "media_actor_link": MediaActorLink, + } + return values +} diff --git a/kontor-echo/internal/handlers/media.go b/kontor-echo/internal/handlers/media.go new file mode 100644 index 0000000..26863aa --- /dev/null +++ b/kontor-echo/internal/handlers/media.go @@ -0,0 +1,26 @@ +package handlers + +import "github.com/uptrace/bun" + +type MediaHandler struct { + MediaArticleHandler *MediaArticleHandler + MediaActorHandler *MediaActorHandler + MediaFileHandler *MediaFileHandler + MediaLoFiHandler *MediaLoFiHandler + MediaMusicHandler *MediaMusicHandler + MediaVideoHandler *MediaVideoHandler + MediaActorFileHandler *MediaActorFileHandler +} + +func NewMediaHandler(db *bun.DB) *MediaHandler { + mediaHandler := &MediaHandler{ + MediaArticleHandler: NewMediaArticleHandler(db), + MediaActorHandler: NewMediaActorHandler(db), + MediaFileHandler: NewMediaFileHandler(db), + MediaLoFiHandler: NewMediaLoFiHandler(db), + MediaMusicHandler: NewMediaMusicHandler(db), + MediaVideoHandler: NewMediaVideoHandler(db), + MediaActorFileHandler: NewMediaActorFileHandler(db), + } + return mediaHandler +} diff --git a/kontor-echo/internal/handlers/media_actor.go b/kontor-echo/internal/handlers/media_actor.go new file mode 100644 index 0000000..e0a5fe8 --- /dev/null +++ b/kontor-echo/internal/handlers/media_actor.go @@ -0,0 +1,137 @@ +package handlers + +import ( + "kontor-api-echo/internal/globals" + "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 MediaActorHandler struct { + Service *service.MediaActorService +} + +func NewMediaActorHandler(db *bun.DB) *MediaActorHandler { + mediaActorHandler := &MediaActorHandler{ + Service: service.NewMediaActorService(repository.NewMediaActorRepository(db)), + } + return mediaActorHandler +} + +func (handler *MediaActorHandler) List(c *echo.Context) { + lofis, err := handler.Service.List(c.Request().Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + dtos := models.ConvertMediaActorsToDtos(lofis) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaActorHandler) Get(c *echo.Context) { + id := c.Param("id") + actor, err := handler.Service.Get(c.Request().Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, map[string]string{"error": "sport not found"}) + return + } + c.JSON(http.StatusOK, actor) +} + +func (handler *MediaActorHandler) Add(c *echo.Context) { + var input models.MediaActorAdd + + if err := c.Bind(&input); err != nil { + c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) + return + } + actor, err := handler.Service.Add(c.Request().Context(), input.WebLink) + if err != nil { + c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not added"}) + return + } + c.JSON(http.StatusOK, actor) +} + +func (handler *MediaActorHandler) Delete(c *echo.Context) { + id := c.Param("id") + err := handler.Service.Delete(c.Request().Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, map[string]string{"error": "sport not found"}) + return + } + c.JSON(http.StatusOK, map[string]string{"ok": "true"}) +} + +func (handler *MediaActorHandler) ListPage(c *echo.Context) { + 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 + } + data := globals.GetDefaultValues(user, "MediaActors...") + data["actors"] = actors + c.Render(http.StatusOK, "media_actors", data) +} + +func (handler *MediaActorHandler) EditPage(c *echo.Context) { + 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 + } + data := globals.GetDefaultValues(user, "MediaActors...") + data["actor"] = actor + c.Render(http.StatusOK, "actor_detail", data) +} + +func (handler *MediaActorHandler) UpdatePage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + var form models.MediaActorForm + if err := c.Bind(&form); err != nil { + logger.Info("MediaActorHandler#UpdatePage", "error", err.Error()) + data := globals.GetDefaultValues(user, "MediaActors...") + data["actor"] = actor + data["Form"] = form + data["Errors"] = err.Error() + c.Render(http.StatusBadRequest, "actor_detail", data) + return + } + logger.Info("MediaActorHandler#UpdatePage", "actor", actor) + //handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO()) + c.Redirect(http.StatusFound, globals.MediaActorLink) +} + +func (handler *MediaActorHandler) DeletePage(c *echo.Context) { + //session := sessions.Default(c) + //user := session.Get(globals.UserKey) + id := c.Param("id") + logger := c.Logger() + //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()}) + // return + // } + logger.Info("MediaActorHandler#DeletePage", "actor", id) + c.Redirect(http.StatusFound, globals.MediaActorLink) +} diff --git a/kontor-echo/internal/handlers/media_actor_file.go b/kontor-echo/internal/handlers/media_actor_file.go new file mode 100644 index 0000000..237682b --- /dev/null +++ b/kontor-echo/internal/handlers/media_actor_file.go @@ -0,0 +1,86 @@ +package handlers + +import ( + "kontor-api-gin/internal/globals" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "net/http" + + "github.com/gin-contrib/sessions" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type MediaActorFileHandler struct { + Service *service.MediaActorFileService +} + +func NewMediaActorFileHandler(db *gorm.DB) *MediaActorFileHandler { + mediaActorFileHandler := &MediaActorFileHandler{ + Service: service.NewMediaActorFileService(repository.NewMediaActorFileRepository(db)), + } + return mediaActorFileHandler +} + +func (handler *MediaActorFileHandler) List(c *gin.Context) { + media_actor_files, err := handler.Service.List(c.Request.Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + dtos := models.ConvertMediaActorFilesToDtos(media_actor_files) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaActorFileHandler) Get(c *gin.Context) { + id := c.Param("id") + actor, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "sport not found"}) + return + } + c.JSON(http.StatusOK, actor) +} + +func (handler *MediaActorFileHandler) Add(c *gin.Context) { + var input models.MediaActorFileAdd + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + actorfile, err := handler.Service.Add(c.Request.Context(), input.MediaActorID, input.MediaFileID) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "lofi not added"}) + return + } + c.JSON(http.StatusOK, actorfile) +} + +func (handler *MediaActorFileHandler) Delete(c *gin.Context) { + id := c.Param("id") + err := handler.Service.Delete(c.Request.Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "sport not found"}) + return + } + c.JSON(http.StatusOK, gin.H{"ok": "true"}) +} + +func (handler *MediaActorFileHandler) ListPage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + media_actor_files, err := handler.Service.List(c.Request.Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.HTML(http.StatusOK, "mediaactorfiles", gin.H{ + "title": "Kontor MediaActorFiles", + "version": "0.4.0", + "message": "MediaActorFiles...", + "actors": media_actor_files, + "user": user, + }) +} diff --git a/kontor-echo/internal/handlers/media_article.go b/kontor-echo/internal/handlers/media_article.go new file mode 100644 index 0000000..2c38b1c --- /dev/null +++ b/kontor-echo/internal/handlers/media_article.go @@ -0,0 +1,115 @@ +package handlers + +import ( + "kontor-api-echo/internal/globals" + "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 MediaArticleHandler struct { + Service *service.MediaArticleService +} + +func NewMediaArticleHandler(db *bun.DB) *MediaArticleHandler { + mediaFileHandler := &MediaArticleHandler{ + Service: service.NewMediaArticleService(repository.NewMediaArticleRepository(db)), + } + return mediaFileHandler +} + +func (handler *MediaArticleHandler) List(c *echo.Context) { + 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 + } + dtos := models.ConvertMediaArticlesToDtos(articles) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaArticleHandler) Delete(c *echo.Context) { + 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 + } + c.JSON(http.StatusOK, map[string]string{"ok": "true"}) +} + +func (handler *MediaArticleHandler) ListPage(c *echo.Context) { + 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 + } + data := globals.GetDefaultValues(user, "MediaArticles...") + data["title"] = "Kontor MediaArticles" + data["media_links"] = files + data["MediaLinksUrl"] = globals.MediaArticleLink + c.Render(http.StatusOK, "media_links", data) +} + +func (handler *MediaArticleHandler) EditPage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + 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) +} + +func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + var form models.MediaArticleForm + if err := c.Bind(&form); err != nil { + logger.Info("MediaArticleHandler#UpdatePage", "error", err.Error()) + data := globals.GetDefaultValues(user, "MediaArticle Details...") + data["Form"] = form + data["Errors"] = err.Error() + c.Render(http.StatusBadRequest, "lofi_detail", data) + return + } + logger.Info("MediaArticleHandler#UpdatePage", "media_article", media_article) + //handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO()) + c.Redirect(http.StatusFound, globals.MediaArticleLink) +} + +func (handler *MediaArticleHandler) DeletePage(c *echo.Context) { + 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 + } + logger.Info("MediaArticleHandler#DeletePage", "lofi", id) + c.Redirect(http.StatusFound, globals.MediaArticleLink) +} diff --git a/kontor-echo/internal/handlers/media_file.go b/kontor-echo/internal/handlers/media_file.go new file mode 100644 index 0000000..c4c5e02 --- /dev/null +++ b/kontor-echo/internal/handlers/media_file.go @@ -0,0 +1,132 @@ +package handlers + +import ( + "kontor-api-gin/internal/globals" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "net/http" + + "github.com/labstack/echo/v5" + "github.com/uptrace/bun" +) + +type MediaFileHandler struct { + Service *service.MediaFileService +} + +func NewMediaFileHandler(db *bun.DB) *MediaFileHandler { + mediaFileHandler := &MediaFileHandler{ + Service: service.NewMediaFileService(repository.NewMediaFileRepository(db)), + } + return mediaFileHandler +} + +func (handler *MediaFileHandler) List(c *echo.Context) { + 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 + } + dtos := models.ConvertMediaFilesToDtos(files) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaFileHandler) Add(c *echo.Context) { + var input models.MediaFileAdd + + if err := c.Bind(&input); err != nil { + c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) + return + } + 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 + } + c.JSON(http.StatusOK, lofi) +} + +func (handler *MediaFileHandler) Delete(c *echo.Context) { + 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 + } + c.JSON(http.StatusOK, map[string]string{"ok": "true"}) +} + +func (handler *MediaFileHandler) ListPage(c *echo.Context) { + 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 + } + data := globals.GetDefaultValues(user, "MediaFiles...") + data["title"] = "Kontor MediaFiles" + data["media_links"] = files + data["MediaLinksUrl"] = globals.MediaVideoLink + c.Render(http.StatusOK, "media_links", data) +} + +func (handler *MediaFileHandler) EditPage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + 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) +} + +func (handler *MediaFileHandler) UpdatePage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + var form models.MediaFileForm + if err := c.Bind(&form); err != nil { + logger.Info("MediaFileHandler#UpdatePage", "error", err.Error()) + data := globals.GetDefaultValues(user, "MediaFile Details...") + data["Form"] = form + data["Errors"] = err.Error() + c.Render(http.StatusBadRequest, "lofi_detail", data) + return + } + logger.Info("MediaFileHandler#UpdatePage", "media_file", media_file) + //handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO()) + c.Redirect(http.StatusFound, globals.MediaFileLink) +} + +func (handler *MediaFileHandler) DeletePage(c *echo.Context) { + //session := sessions.Default(c) + //user := session.Get(globals.UserKey) + id := c.Param("id") + logger := c.Logger() + 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 + } + logger.Info("MediaFileHandler#DeletePage", "lofi", id) + c.Redirect(http.StatusFound, globals.MediaFileLink) +} diff --git a/kontor-echo/internal/handlers/media_lofi.go b/kontor-echo/internal/handlers/media_lofi.go new file mode 100644 index 0000000..c21276d --- /dev/null +++ b/kontor-echo/internal/handlers/media_lofi.go @@ -0,0 +1,233 @@ +package handlers + +import ( + "kontor-api-gin/internal/globals" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "net/http" + "time" + + "github.com/gin-contrib/sessions" + "github.com/google/uuid" + "github.com/labstack/echo/v5" + "github.com/uptrace/bun" +) + +type MediaLoFiHandler struct { + Service *service.MediaLoFiService +} + +func NewMediaLoFiHandler(db *bun.DB) *MediaLoFiHandler { + mediaLoFiHandler := &MediaLoFiHandler{ + Service: service.NewMediaLoFiService(repository.NewMediaLoFiRepository(db)), + } + return mediaLoFiHandler +} + +func (handler *MediaLoFiHandler) List(c *echo.Context) { + lofis, err := handler.Service.List(c.Request().Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + dtos := models.ConvertMediaLoFisToDtos(lofis) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaLoFiHandler) Get(c *echo.Context) { + id := c.Param("id") + lofi, err := handler.Service.Get(c.Request().Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, map[string]string{"error": "Lofi not found"}) + return + } + c.JSON(http.StatusOK, lofi) +} + +func (handler *MediaLoFiHandler) Add(c *echo.Context) { + var input models.MediaLofiAdd + + if err := c.Bind(&input); err != nil { + c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) + return + } + 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 + } + c.JSON(http.StatusOK, lofi) +} + +func (handler *MediaLoFiHandler) Update(c *echo.Context) { + var input models.MediaLoFiDTO + + if err := c.Bind(&input); err != nil { + c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) + return + } + 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 + } + c.JSON(http.StatusOK, lofi) +} +func (handler *MediaLoFiHandler) Delete(c *echo.Context) { + 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 + } + c.JSON(http.StatusOK, map[string]string{"ok": "true"}) +} + +func (handler *MediaLoFiHandler) ListPage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + logger := c.Logger() + var ( + review bool + download bool + ) + paramReview, err := echo.QueryParam[string](c, "review") + if err == nil { + if paramReview == "on" { + review = true + } else { + review = false + } + } + paramDownload, err := echo.QueryParam[string](c, "should_download") + if err == nil { + if paramDownload == "on" { + download = true + } else { + download = false + } + } + + 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 + } + logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis)) + data := globals.GetDefaultValues(user, "MediaFiles...") + data["media_links"] = lofis + data["isReview"] = review + data["isDownload"] = download + data["MediaLinksUrl"] = globals.MediaLofiLink + c.Render(http.StatusOK, "media_links", data) +} + +func (handler *MediaLoFiHandler) EditPage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + var lofi *models.MediaLoFi + if id == "" { + // id is empty, adding is assumed + lofi = &models.MediaLoFi{ + ID: uuid.NewString(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + Version: 0, + Review: true, + ShouldDownload: true, + } + } else { + // id is set, fetch MediaLofi by ID + 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 + } + } + 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) +} + +func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) { + 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 + } + lofi.Review = !lofi.Review + handler.Service.Update(c.Request().Context(), lofi.ConvertMediaLoFiToDTO()) + logger.Info("MediaLoFiHandler#ChangeReviewPage", "lofi", lofi) + session := sessions.Default(c) + user := session.Get(globals.UserKey) + 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 + } + 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) +} + +func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + 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]string{ + "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) +} + +func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) { + cookie, err := c.Cookie(globals.UserKey) + user := cookie.Value + id := c.Param("id") + logger := c.Logger() + 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 + } + logger.Info("MediaLoFiHandler#DeletePage", "lofi", id) + c.Render(http.StatusOK, "lofi_delete", map[string]string{ + "title": "Kontor MediaFiles", + "version": "0.4.0", + "message": "MediaFiles...", + "lofi": lofi, + "user": user, + }) +} diff --git a/kontor-echo/internal/handlers/media_music.go b/kontor-echo/internal/handlers/media_music.go new file mode 100644 index 0000000..14ddf5f --- /dev/null +++ b/kontor-echo/internal/handlers/media_music.go @@ -0,0 +1,183 @@ +package handlers + +import ( + "kontor-api-gin/internal/globals" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "net/http" + + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/slog" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type MediaMusicHandler struct { + Service *service.MediaMusicService +} + +func NewMediaMusicHandler(db *gorm.DB) *MediaMusicHandler { + mediaMusicHandler := &MediaMusicHandler{ + Service: service.NewMediaMusicService(repository.NewMediaMusicRepository(db)), + } + return mediaMusicHandler +} + +func (handler *MediaMusicHandler) List(c *gin.Context) { + musics, err := handler.Service.List(c.Request.Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + dtos := models.ConvertMediaMusicsToDtos(musics) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaMusicHandler) Get(c *gin.Context) { + id := c.Param("id") + music, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "MediaMusic not found"}) + return + } + c.JSON(http.StatusOK, music) +} + +func (handler *MediaMusicHandler) Add(c *gin.Context) { + var input models.MediaLofiAdd + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + music, err := handler.Service.Add(c.Request.Context(), input.Url) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "MediaMusic not added"}) + return + } + c.JSON(http.StatusOK, music) +} + +func (handler *MediaMusicHandler) Update(c *gin.Context) { + var input models.MediaMusicDTO + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + music, err := handler.Service.Update(c.Request.Context(), input) + if err != nil { + logger := slog.Get(c) + logger.Info("MediaMusicHandler#Update", "error", err.Error()) + c.JSON(http.StatusNotFound, gin.H{"error": "MediaMusic not updated"}) + return + } + c.JSON(http.StatusOK, music) +} +func (handler *MediaMusicHandler) Delete(c *gin.Context) { + id := c.Param("id") + err := handler.Service.Delete(c.Request.Context(), id) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "MediaMusic not found"}) + return + } + c.JSON(http.StatusOK, gin.H{"ok": "true"}) +} + +func (handler *MediaMusicHandler) ListPage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + logger := slog.Get(c) + var ( + review bool + download bool + ) + paramReview, existsReview := c.GetQuery("review") + if existsReview { + if paramReview == "on" { + review = true + } else { + review = false + } + } + paramDownload, existsDownload := c.GetQuery("should_download") + if existsDownload { + if paramDownload == "on" { + download = true + } else { + download = false + } + } + + musics, err := handler.Service.List(c.Request.Context()) + if err != nil { + logger.Info("MediaMusicHandler#ListPage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + logger.Info("MediaMusicHandler#ListPage", "MediaMusic count", len(musics)) + data := globals.GetDefaultValues(user, "MediaMusic...") + data["media_links"] = musics + data["MediaLinksUrl"] = globals.MediaMusicLink + data["isReview"] = review + data["isDownload"] = download + c.HTML(http.StatusOK, "media_links", data) +} + +func (handler *MediaMusicHandler) EditPage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + music, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + logger.Info("MediaMusicHandler#EditPage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + logger.Info("MediaMusicHandler#EditPage", "music", music) + data := globals.GetDefaultValues(user, "MediaMusic...") + data["lofi"] = music + c.HTML(http.StatusOK, "lofi_detail", data) +} + +func (handler *MediaMusicHandler) UpdatePage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + music, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + logger.Info("MediaMusicHandler#UpdatePage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + var form models.MediaMusicForm + if err := c.ShouldBind(&form); err != nil { + logger.Info("MediaMusicHandler#UpdatePage", "error", err.Error()) + data := globals.GetDefaultValues(user, "MediaMusic...") + data["Form"] = form + data["Errors"] = err.Error() + c.HTML(http.StatusBadRequest, "lofi_detail", data) + return + } + logger.Info("MediaMusicHandler#UpdatePage", "music", music) + //handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO()) + c.Redirect(http.StatusFound, globals.MediaMusicLink) +} + +func (handler *MediaMusicHandler) DeletePage(c *gin.Context) { + // session := sessions.Default(c) + // user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + err := handler.Service.Delete(c.Request.Context(), id) + if err != nil { + logger.Info("MediaMusicHandler#DeletePage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + logger.Info("MediaMusicHandler#DeletePage", "music", id) + c.Redirect(http.StatusFound, globals.MediaMusicLink) +} diff --git a/kontor-echo/internal/handlers/mediavideo.go b/kontor-echo/internal/handlers/mediavideo.go new file mode 100644 index 0000000..4f33ba9 --- /dev/null +++ b/kontor-echo/internal/handlers/mediavideo.go @@ -0,0 +1,115 @@ +package handlers + +import ( + "kontor-api-gin/internal/globals" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "net/http" + + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/slog" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type MediaVideoHandler struct { + Service *service.MediaVideoService +} + +func NewMediaVideoHandler(db *gorm.DB) *MediaVideoHandler { + handler := &MediaVideoHandler{Service: service.NewMediaVideoService(repository.NewMediaVideoRepository(db))} + return handler +} + +func (handler *MediaVideoHandler) List(c *gin.Context) { + logger := slog.Get(c) + logger.Info("MediaVideoHandler#List") + videos, err := handler.Service.List(c.Request.Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + dtos := models.ConvertMediaVideosToDtos(videos) + c.JSON(http.StatusOK, dtos) +} + +func (handler *MediaVideoHandler) ListPage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + logger := slog.Get(c) + videos, err := handler.Service.List(c.Request.Context()) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + 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.HTML(http.StatusOK, "media_links", data) +} + +func (handler *MediaVideoHandler) EditPage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + video, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + logger.Info("MediaVideoHandler#EditPage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + logger.Info("MediaVideoHandler#EditPage", "lofi", video) + data := globals.GetDefaultValues(user, "MediaLofis...") + data["lofi"] = video + c.HTML(http.StatusOK, "lofi_detail", data) +} + +func (handler *MediaVideoHandler) UpdatePage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + video, err := handler.Service.Get(c.Request.Context(), id) + if err != nil { + logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + var form models.MediaVideoForm + if err := c.ShouldBind(&form); err != nil { + logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error()) + c.HTML(http.StatusBadRequest, "lofi_detail", gin.H{ + "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) +} + +func (handler *MediaVideoHandler) DeletePage(c *gin.Context) { + session := sessions.Default(c) + user := session.Get(globals.UserKey) + id := c.Param("id") + logger := slog.Get(c) + err := handler.Service.Delete(c.Request.Context(), id) + if err != nil { + logger.Info("MediaVideoHandler#DeletePage", "error", err.Error()) + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + logger.Info("MediaVideoHandler#DeletePage", "video", id) + c.HTML(http.StatusOK, "lofi_delete", gin.H{ + "title": "Kontor MediaFiles", + "version": "0.4.0", + "message": "MediaFiles...", + "user": user, + }) +} diff --git a/kontor-echo/internal/helpers/time.go b/kontor-echo/internal/helpers/time.go new file mode 100644 index 0000000..f61b4b4 --- /dev/null +++ b/kontor-echo/internal/helpers/time.go @@ -0,0 +1,69 @@ +package helpers + +import ( + "encoding/json" + "fmt" + "time" +) + +type DateOnly struct { + time.Time +} + +func (d DateOnly) MarshalJSON() ([]byte, error) { + if d.IsZero() { + return []byte("null"), nil + } + return json.Marshal(d.Format("2006-01-02")) +} + +func (d *DateOnly) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + if s == "" { + return nil + } + t, err := time.Parse("2006-01-02", s) + if err != nil { + return err + } + d.Time = t + return nil +} + +type KontorTime struct { + time.Time +} + +var layouts = []string{ + "2006-01-02 15:04:05.000000", + "2006-01-02T15:04:05.999Z", + "2006-01-02", +} + +func (kt KontorTime) MarshalJSON() ([]byte, error) { + if kt.IsZero() { + return []byte("null"), nil + } + return json.Marshal(kt.Format(layouts[0])) +} + +func (kt *KontorTime) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + if s == "" { + return nil + } + for _, layout := range layouts { + t, err := time.Parse(layout, s) + if err == nil { + kt.Time = t + return nil + } + } + return fmt.Errorf("failed to parse time from %s", s) +} diff --git a/kontor-echo/internal/models/media_actor.go b/kontor-echo/internal/models/media_actor.go index 0fd68cf..2ac67e8 100644 --- a/kontor-echo/internal/models/media_actor.go +++ b/kontor-echo/internal/models/media_actor.go @@ -1,6 +1,7 @@ -package schema +package models import ( + "kontor-api-echo/internal/helpers" "time" "github.com/uptrace/bun" @@ -9,13 +10,63 @@ import ( type MediaActor struct { bun.BaseModel `bun:"table:media_actor"` - 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"` - Version int `bun:"version,default:0"` - Name string `bun:"name"` - WebLink string `bun:"url,unique:url"` + 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"` + Name string `bun:"name"` + WebLink string `bun:"url,unique:url"` MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_actor_id"` } +type MediaActorForm struct { + Name string `form:"name" binding:"required"` + Weblink string `form:"weblink" binding:"required"` +} + +type MediaActorDTO 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"` + Name string `json:"name"` + WebLink string `json:"url"` +} + +func (dto MediaActorDTO) ConvertDTOToModel() MediaActor { + model := MediaActor{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + Name: dto.Name, + WebLink: dto.WebLink, + } + return model +} + +type MediaActorAdd struct { + WebLink string `json:"url"` +} + +func ConvertMediaActorsToDtos(actors []MediaActor) []MediaActorDTO { + dtos := make([]MediaActorDTO, len(actors)) + for i, actor := range actors { + dtos[i] = MediaActorDTO{ + ID: actor.ID, + CreatedAt: helpers.KontorTime{Time: actor.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: actor.UpdatedAt}, + DeletedAt: actor.DeletedAt, + Version: actor.Version, + Name: actor.Name, + WebLink: actor.WebLink, + } + } + return dtos +} + +type MediaActorDTOList []MediaActorDTO diff --git a/kontor-echo/internal/models/media_actor_file.go b/kontor-echo/internal/models/media_actor_file.go index 9448989..051c25d 100644 --- a/kontor-echo/internal/models/media_actor_file.go +++ b/kontor-echo/internal/models/media_actor_file.go @@ -1,6 +1,7 @@ -package schema +package models import ( + "kontor-api-echo/internal/helpers" "time" "github.com/uptrace/bun" @@ -12,6 +13,7 @@ type MediaActorFile struct { 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"` MediaActorID *string `bun:"media_actor_id"` MediaActor *MediaActor `bun:"rel:belongs-to,join:media_actor_id=id"` @@ -19,3 +21,48 @@ type MediaActorFile struct { MediaFile *MediaFile `bun:"rel:belongs-to,join:media_file_id=id"` } +type MediaActorFileAdd struct { + MediaActorID string `json:"media_actor_id"` + MediaFileID string `json:"media_file_id"` +} + +type MediaActorFileDTO 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"` + MediaActorID *string `json:"media_actor_id"` + MediaFileID *string `json:"media_file_id"` +} + +func (dto MediaActorFileDTO) ConvertDTOToModel() MediaActorFile { + model := MediaActorFile{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + MediaActorID: dto.MediaActorID, + MediaFileID: dto.MediaFileID, + } + return model +} + +func ConvertMediaActorFilesToDtos(actor_files []MediaActorFile) []MediaActorFileDTO { + dtos := make([]MediaActorFileDTO, len(actor_files)) + for i, actor_file := range actor_files { + dtos[i] = MediaActorFileDTO{ + ID: actor_file.ID, + CreatedAt: helpers.KontorTime{Time: actor_file.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: actor_file.UpdatedAt}, + DeletedAt: actor_file.DeletedAt, + Version: actor_file.Version, + MediaActorID: actor_file.MediaActorID, + MediaFileID: actor_file.MediaFileID, + } + } + return dtos +} + +type MediaActorFileDTOList []MediaActorFileDTO diff --git a/kontor-echo/internal/models/media_article.go b/kontor-echo/internal/models/media_article.go index f2b5a4f..5290821 100644 --- a/kontor-echo/internal/models/media_article.go +++ b/kontor-echo/internal/models/media_article.go @@ -1,79 +1,80 @@ -package schema +package models import ( + "kontor-api-echo/internal/helpers" "time" "github.com/uptrace/bun" ) -type MediaFile struct { - bun.BaseModel `bun:"table:media_file"` - - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` - - MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_file_id"` -} - -type MediaActor struct { - bun.BaseModel `bun:"table:media_actor"` - - 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"` - Version int `bun:"version,default:0"` - Name string `bun:"name"` - WebLink string `bun:"url,unique:url"` - - MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_actor_id"` -} - -type MediaActorFile struct { - bun.BaseModel `bun:"table:media_actor_file"` - - 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"` - Version int `bun:"version,default:0"` - MediaActorID *string `bun:"media_actor_id"` - MediaActor *MediaActor `bun:"rel:belongs-to,join:media_actor_id=id"` - MediaFileID *string `bun:"media_file_id"` - MediaFile *MediaFile `bun:"rel:belongs-to,join:media_file_id=id"` -} - type MediaArticle struct { bun.BaseModel `bun:"table:media_article"` - 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"` - Version int `bun:"version,default:0"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` + 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"` + Review bool `bun:"review"` + Title string `bun:"title"` + WebLink string `bun:"url,unique:url"` } -type MediaVideo struct { - bun.BaseModel `bun:"table:media_article"` - - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` +func (media_article MediaArticle) ConvertMediaArticleToDTO() MediaArticleDTO { + dto := MediaArticleDTO{ + ID: media_article.ID, + CreatedAt: helpers.KontorTime{Time: media_article.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: media_article.UpdatedAt}, + DeletedAt: media_article.DeletedAt, + Version: media_article.Version, + Review: media_article.Review, + Title: media_article.Title, + WebLink: media_article.WebLink, + } + return dto } + +type MediaArticleForm struct { + Title string `form:"title" binding:"required"` + Url string `form:"url" binding:"required"` +} + +func (form *MediaArticleForm) ConvertFormToMediaArticleDTO() MediaArticleDTO { + dto := MediaArticleDTO{} + return dto +} + +type MediaArticleDTO 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"` + Version int `json:"version"` + Review bool `json:"review"` + Title string `json:"title"` + WebLink string `json:"url"` +} + +func (dto MediaArticleDTO) ConvertDTOToModel() MediaArticle { + model := MediaArticle{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + Review: dto.Review, + Title: dto.Title, + WebLink: dto.WebLink, + } + return model +} + +func ConvertMediaArticlesToDtos(media_articles []MediaArticle) MediaArticleDTOList { + dtos := make(MediaArticleDTOList, len(media_articles)) + for i, media_article := range media_articles { + dtos[i] = media_article.ConvertMediaArticleToDTO() + } + return dtos +} + +type MediaArticleDTOList []MediaArticleDTO diff --git a/kontor-echo/internal/models/media_file.go b/kontor-echo/internal/models/media_file.go index df47c72..097c87d 100644 --- a/kontor-echo/internal/models/media_file.go +++ b/kontor-echo/internal/models/media_file.go @@ -1,6 +1,7 @@ package models import ( + "kontor-api-echo/internal/helpers" "time" "github.com/uptrace/bun" @@ -9,18 +10,88 @@ import ( type MediaFile struct { bun.BaseModel `bun:"table:media_file"` - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` + 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"` + CloudLink string `bun:"cloud_link"` + FileName string `bun:"file_name"` + Path string `bun:"path"` + Review bool `bun:"review"` + Title string `bun:"title"` + WebLink string `bun:"url,unique:url"` + ShouldDownload bool `bun:"should_download"` MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_file_id"` } +type MediaFileAdd struct { + Url string `json:"url"` +} + +type MediaFileForm struct { + Title string `form:"title" binding:"required"` + Url string `form:"url" binding:"required"` +} + +func (form *MediaFileForm) ConvertFormToMediaFileDTO() MediaFileDTO { + media_file := MediaFileDTO{} + return media_file +} + +type MediaFileDTO 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"` + CloudLink string `json:"cloud_link"` + FileName string `json:"file_name"` + Path string `json:"path"` + Review bool `json:"review"` + Title string `json:"title"` + WebLink string `json:"url"` + ShouldDownload bool `json:"should_download"` +} + +func (dto MediaFileDTO) ConvertDTOToModel() MediaFile { + model := MediaFile{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + CloudLink: dto.CloudLink, + FileName: dto.FileName, + Path: dto.Path, + Review: dto.Review, + ShouldDownload: dto.ShouldDownload, + Title: dto.Title, + WebLink: dto.WebLink, + } + return model +} + +func ConvertMediaFilesToDtos(media_files []MediaFile) []MediaFileDTO { + dtos := make([]MediaFileDTO, len(media_files)) + for i, media_file := range media_files { + dtos[i] = MediaFileDTO{ + ID: media_file.ID, + CreatedAt: helpers.KontorTime{Time: media_file.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: media_file.UpdatedAt}, + DeletedAt: media_file.DeletedAt, + Version: media_file.Version, + CloudLink: media_file.CloudLink, + FileName: media_file.FileName, + Path: media_file.Path, + Review: media_file.Review, + Title: media_file.Title, + WebLink: media_file.WebLink, + ShouldDownload: media_file.ShouldDownload, + } + } + return dtos +} + +type MediaFileDTOList []MediaFileDTO diff --git a/kontor-echo/internal/models/media_lofi.go b/kontor-echo/internal/models/media_lofi.go new file mode 100644 index 0000000..208e0a5 --- /dev/null +++ b/kontor-echo/internal/models/media_lofi.go @@ -0,0 +1,193 @@ +package models + +import ( + "fmt" + "kontor-api-echo/internal/config" + "kontor-api-echo/internal/helpers" + "log/slog" + "time" + + "github.com/uptrace/bun" +) + +type MediaLoFi struct { + bun.BaseModel `bun:"table:media_lofi"` + + 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"` + WebLink string `bun:"url,unique:url"` + Review bool `bun:"review"` + ShouldDownload bool `bun:"should_download"` + Title string `bun:"title"` + FileName string `bun:"file_name"` +} + +func (media_lofi *MediaLoFi) Update(update MediaLoFiDTO) { + media_lofi.CreatedAt = update.CreatedAt.Time + media_lofi.UpdatedAt = time.Now() + media_lofi.Version = media_lofi.Version + 1 + media_lofi.WebLink = update.WebLink + media_lofi.Review = update.Review + media_lofi.ShouldDownload = update.ShouldDownload + media_lofi.Title = update.Title + media_lofi.FileName = update.FileName +} + +func (media_lofi *MediaLoFi) ConvertMediaLoFiToDTO() MediaLoFiDTO { + dto := MediaLoFiDTO{ + ID: media_lofi.ID, + CreatedAt: helpers.KontorTime{Time: media_lofi.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: media_lofi.UpdatedAt}, + DeletedAt: media_lofi.DeletedAt, + Version: media_lofi.Version, + WebLink: media_lofi.WebLink, + Review: media_lofi.Review, + ShouldDownload: media_lofi.ShouldDownload, + Title: media_lofi.Title, + FileName: media_lofi.FileName, + } + return dto +} + +type MediaLofiAdd struct { + Url string `json:"url"` +} + +type MediaLoFiForm struct { + Title string `form:"title" binding:"required"` + Url string `form:"url" binding:"required"` +} + +func (form *MediaLoFiForm) ConvertFormToMediaLofiDTO() MediaLoFiDTO { + media_lofi := MediaLoFiDTO{} + return media_lofi +} + +type MediaLoFiDTO 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"` + FileName string `json:"file_name"` + Review bool `json:"review"` + ShouldDownload bool `json:"should_download"` + Title string `json:"title"` + WebLink string `json:"url"` +} + +func (dto MediaLoFiDTO) ConvertDTOToModel() MediaLoFi { + model := MediaLoFi{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + FileName: dto.FileName, + Review: dto.Review, + ShouldDownload: dto.ShouldDownload, + Title: dto.Title, + WebLink: dto.WebLink, + } + return model +} + +func (source MediaLoFiDTO) Equals(target MediaLoFiDTO) bool { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals", "id", source.ID) + } + equals := true + if source.Title != target.Title { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: Title changed") + } + equals = false + } + if source.WebLink != target.WebLink { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: WebLink changed") + } + equals = false + } + if source.Version != target.Version { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: Version changed") + } + equals = false + } + if source.FileName != target.FileName { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: FileName changed") + } + equals = false + } + if source.Review != target.Review { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: Review changed") + } + equals = false + } + if source.ShouldDownload != target.ShouldDownload { + if config.Verbose > 1 { + slog.Info("MediaLoFiDTO#Equals: ShouldDownload changed") + } + equals = false + } + return equals +} + +type MediaLoFiDTOList []MediaLoFiDTO + +func (source MediaLoFiDTOList) GetMediaLofi(lofi_id string) *MediaLoFiDTO { + for _, lofi := range source { + if lofi.ID == lofi_id { + return &lofi + } + } + return nil +} + +func (source *MediaLoFiDTOList) CompareIds(target *MediaLoFiDTOList) (missing, obsolete, changed []string) { + sources := make(map[string]MediaLoFiDTO, len(*source)) + targets := make(map[string]MediaLoFiDTO, len(*target)) + for _, source := range *source { + sources[source.ID] = source + } + for _, target := range *target { + targets[target.ID] = target + } + // iterate source IDs + for id := range sources { + if _, ok := targets[id]; ok { + if config.Verbose > 1 { + slog.Info(fmt.Sprintf("ID %s found in both lists", id)) + } + if !sources[id].Equals(targets[id]) { + changed = append(changed, id) + } + } else { + missing = append(missing, id) + } + } + for id := range targets { + if _, ok := sources[id]; ok { + slog.Debug(fmt.Sprintf("ID %s found in both lists", id)) + } else { + obsolete = append(obsolete, id) + } + } + slog.Info("CompareIds", "missing", len(missing), "obsolete", len(obsolete), "changed", len(changed)) + slog.Debug("CompareIds", "missing", missing, "obsolete", obsolete) + return missing, obsolete, changed +} + +func ConvertMediaLoFisToDtos(media_lofis []MediaLoFi) MediaLoFiDTOList { + dtos := make(MediaLoFiDTOList, len(media_lofis)) + for i, media_lofi := range media_lofis { + dtos[i] = media_lofi.ConvertMediaLoFiToDTO() + } + return dtos +} diff --git a/kontor-echo/internal/models/media_music.go b/kontor-echo/internal/models/media_music.go new file mode 100644 index 0000000..04861dc --- /dev/null +++ b/kontor-echo/internal/models/media_music.go @@ -0,0 +1,193 @@ +package models + +import ( + "fmt" + "kontor-api-echo/internal/config" + "kontor-api-echo/internal/helpers" + "log/slog" + "time" + + "github.com/uptrace/bun" +) + +type MediaMusic struct { + bun.BaseModel `bun:"table:media_music"` + + 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"` + WebLink string `bun:"url,unique:url"` + Review bool `bun:"review"` + ShouldDownload bool `bun:"should_download"` + Title string `bun:"title"` + FileName string `bun:"file_name"` +} + +func (media_music *MediaMusic) Update(update MediaMusicDTO) { + media_music.CreatedAt = update.CreatedAt.Time + media_music.UpdatedAt = time.Now() + media_music.Version = media_music.Version + 1 + media_music.WebLink = update.WebLink + media_music.Review = update.Review + media_music.ShouldDownload = update.ShouldDownload + media_music.Title = update.Title + media_music.FileName = update.FileName +} + +func (media_music *MediaMusic) ConvertMediaMusicToDTO() MediaMusicDTO { + dto := MediaMusicDTO{ + ID: media_music.ID, + CreatedAt: helpers.KontorTime{Time: media_music.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: media_music.UpdatedAt}, + DeletedAt: media_music.DeletedAt, + Version: media_music.Version, + WebLink: media_music.WebLink, + Review: media_music.Review, + ShouldDownload: media_music.ShouldDownload, + Title: media_music.Title, + FileName: media_music.FileName, + } + return dto +} + +type MediaMusicAdd struct { + Url string `json:"url"` +} + +type MediaMusicForm struct { + Title string `form:"title" binding:"required"` + Url string `form:"url" binding:"required"` +} + +func (form *MediaMusicForm) ConvertFormToMediaMusicDTO() MediaMusicDTO { + media_music := MediaMusicDTO{} + return media_music +} + +type MediaMusicDTO 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"` + FileName string `json:"file_name"` + Review bool `json:"review"` + ShouldDownload bool `json:"should_download"` + Title string `json:"title"` + WebLink string `json:"url"` +} + +func (dto MediaMusicDTO) ConvertDTOToModel() MediaMusic { + model := MediaMusic{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + FileName: dto.FileName, + Review: dto.Review, + ShouldDownload: dto.ShouldDownload, + Title: dto.Title, + WebLink: dto.WebLink, + } + return model +} + +func (source MediaMusicDTO) Equals(target MediaMusicDTO) bool { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals", "id", source.ID) + } + equals := true + if source.Title != target.Title { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: Title changed") + } + equals = false + } + if source.WebLink != target.WebLink { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: WebLink changed") + } + equals = false + } + if source.Version != target.Version { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: Version changed") + } + equals = false + } + if source.FileName != target.FileName { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: FileName changed") + } + equals = false + } + if source.Review != target.Review { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: Review changed") + } + equals = false + } + if source.ShouldDownload != target.ShouldDownload { + if config.Verbose > 1 { + slog.Info("MediaMusicDTO#Equals: ShouldDownload changed") + } + equals = false + } + return equals +} + +type MediaMusicDTOList []MediaMusicDTO + +func (source MediaMusicDTOList) GetMediaMusic(music_id string) *MediaMusicDTO { + for _, music := range source { + if music.ID == music_id { + return &music + } + } + return nil +} + +func (source *MediaMusicDTOList) CompareIds(target *MediaMusicDTOList) (missing, obsolete, changed []string) { + sources := make(map[string]MediaMusicDTO, len(*source)) + targets := make(map[string]MediaMusicDTO, len(*target)) + for _, source := range *source { + sources[source.ID] = source + } + for _, target := range *target { + targets[target.ID] = target + } + // iterate source IDs + for id := range sources { + if _, ok := targets[id]; ok { + if config.Verbose > 1 { + slog.Info(fmt.Sprintf("ID %s found in both lists", id)) + } + if !sources[id].Equals(targets[id]) { + changed = append(changed, id) + } + } else { + missing = append(missing, id) + } + } + for id := range targets { + if _, ok := sources[id]; ok { + slog.Debug(fmt.Sprintf("ID %s found in both lists", id)) + } else { + obsolete = append(obsolete, id) + } + } + slog.Info("CompareIds", "missing", len(missing), "obsolete", len(obsolete), "changed", len(changed)) + slog.Debug("CompareIds", "missing", missing, "obsolete", obsolete) + return missing, obsolete, changed +} + +func ConvertMediaMusicsToDtos(media_musics []MediaMusic) MediaMusicDTOList { + dtos := make(MediaMusicDTOList, len(media_musics)) + for i, media_music := range media_musics { + dtos[i] = media_music.ConvertMediaMusicToDTO() + } + return dtos +} diff --git a/kontor-echo/internal/models/media_video.go b/kontor-echo/internal/models/media_video.go index d4d487f..e4991c8 100644 --- a/kontor-echo/internal/models/media_video.go +++ b/kontor-echo/internal/models/media_video.go @@ -1,24 +1,98 @@ -package schema +package models import ( + "kontor-api-echo/internal/helpers" "time" "github.com/uptrace/bun" ) type MediaVideo struct { - bun.BaseModel `bun:"table:media_article"` + bun.BaseModel `bun:"table:media_video"` - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` + 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"` + CloudLink string `bun:"cloud_link"` + FileName string `bun:"file_name"` + Path string `bun:"path"` + Review bool `bun:"review"` + Title string `bun:"title"` + WebLink string `bun:"url,unique:url"` + ShouldDownload bool `bun:"should_download"` } +func (media_music *MediaVideo) Update(update MediaVideoDTO) { + media_music.CreatedAt = update.CreatedAt.Time + media_music.UpdatedAt = time.Now() + media_music.Version = media_music.Version + 1 + media_music.WebLink = update.WebLink + media_music.Review = update.Review + media_music.ShouldDownload = update.ShouldDownload + media_music.Title = update.Title + media_music.FileName = update.FileName +} + +type MediaVideoForm struct { + Title string `form:"title" binding:"required"` + Url string `form:"url" binding:"required"` +} + +func (form *MediaVideoForm) ConvertFormToMediaVideoDTO() MediaVideoDTO { + media_video := MediaVideoDTO{} + return media_video +} + +type MediaVideoDTO 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"` + CloudLink string `json:"cloud_link"` + FileName string `json:"file_name"` + Path string `json:"path"` + Review bool `json:"review"` + Title string `json:"title"` + WebLink string `json:"url"` + ShouldDownload bool `json:"should_download"` +} + +func (dto MediaVideoDTO) ConvertDTOToModel() MediaVideo { + model := MediaVideo{ + ID: dto.ID, + CreatedAt: dto.CreatedAt.Time, + UpdatedAt: dto.UpdatedAt.Time, + DeletedAt: dto.DeletedAt, + Version: dto.Version, + Review: dto.Review, + Title: dto.Title, + WebLink: dto.WebLink, + } + return model +} + +func ConvertMediaVideosToDtos(media_videos []MediaVideo) []MediaVideoDTO { + dtos := make([]MediaVideoDTO, len(media_videos)) + for i, media_video := range media_videos { + dtos[i] = MediaVideoDTO{ + ID: media_video.ID, + CreatedAt: helpers.KontorTime{Time: media_video.CreatedAt}, + UpdatedAt: helpers.KontorTime{Time: media_video.UpdatedAt}, + DeletedAt: media_video.DeletedAt, + Version: media_video.Version, + CloudLink: media_video.CloudLink, + FileName: media_video.FileName, + Path: media_video.Path, + Review: media_video.Review, + Title: media_video.Title, + WebLink: media_video.WebLink, + ShouldDownload: media_video.ShouldDownload, + } + } + return dtos +} + +type MediaVideoDTOList []MediaVideoDTO diff --git a/kontor-echo/internal/repository/media_actor.go b/kontor-echo/internal/repository/media_actor.go new file mode 100644 index 0000000..501a68d --- /dev/null +++ b/kontor-echo/internal/repository/media_actor.go @@ -0,0 +1,76 @@ +package repository + +import ( + "context" + "fmt" + "kontor-api-echo/internal/models" + "log/slog" + + "github.com/uptrace/bun" +) + +type MediaActorRepository struct { + db *bun.DB +} + +func (repository *MediaActorRepository) Import(dtos models.MediaActorDTOList) { + slog.Info("MediaActorRepository#Import") + for index, dto := range dtos { + 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 { + 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()) + } + } 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()) + } + } + } +} + +func NewMediaActorRepository(db *bun.DB) *MediaActorRepository { + repo := &MediaActorRepository{db: db} + return repo +} + +func (repository *MediaActorRepository) FindAll(context context.Context) ([]models.MediaActor, error) { + var actors []models.MediaActor + + result := repository.db.Find(&actors) + slog.Info("MediaActorRepository#FindAll", "count", result.RowsAffected) + + return actors, nil +} + +func (repository *MediaActorRepository) GetById(context context.Context, id string) (*models.MediaActor, error) { + var actor = 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()) + } + return &actor, result.Error +} + +func (repository *MediaActorRepository) Add(context context.Context, url string) (*models.MediaActor, error) { + slog.Info("MediaActorRepository#Add", "url", url) + return nil, fmt.Errorf("unimplemented method MediaFileRepository#Add") +} + +func (repository *MediaActorRepository) Delete(context context.Context, id string) error { + var actor = models.MediaActor{ID: id} + slog.Info("MediaActorRepository#Delete", "id", id) + result := repository.db.Delete(&actor) + if result.Error != nil { + slog.Info("SportRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/repository/media_actor_file.go b/kontor-echo/internal/repository/media_actor_file.go new file mode 100644 index 0000000..695a282 --- /dev/null +++ b/kontor-echo/internal/repository/media_actor_file.go @@ -0,0 +1,77 @@ +package repository + +import ( + "context" + "fmt" + "kontor-api-echo/internal/models" + "log/slog" + + "github.com/uptrace/bun" +) + +type MediaActorFileRepository struct { + db *bun.DB +} + +func (repository *MediaActorFileRepository) Import(dtos models.MediaActorFileDTOList) { + slog.Info("MediaActorFileRepository#Import") + for index, dto := range dtos { + 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 { + 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()) + } + } 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()) + } + } + } +} + +func NewMediaActorFileRepository(db *bun.DB) *MediaActorFileRepository { + repo := &MediaActorFileRepository{db: db} + return repo +} + +func (repository *MediaActorFileRepository) FindAll(context context.Context) ([]models.MediaActorFile, error) { + var actor_files []models.MediaActorFile + + result := repository.db.Find(&actor_files) + slog.Info("MediaActorFileRepository#FindAll", "count", result.RowsAffected) + + return actor_files, nil +} + +func (repository *MediaActorFileRepository) GetById(context context.Context, id string) (*models.MediaActorFile, error) { + var actorfile = 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 + } + return &actorfile, result.Error +} + +func (repository *MediaActorFileRepository) Add(context context.Context, media_actor_id, media_file_id string) (*models.MediaActorFile, error) { + slog.Info("MediaActorFileRepository#Add", "actor_id", media_actor_id, "file_id", media_file_id) + return nil, fmt.Errorf("unimplemented method MediaActorFileRepository#Add") +} + +func (repository *MediaActorFileRepository) Delete(context context.Context, id string) error { + var file = models.MediaActorFile{ID: id} + slog.Info("MediaActorFileRepository#Delete", "id", id) + result := repository.db.Delete(&file) + if result.Error != nil { + slog.Info("MediaActorFileRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/repository/media_article.go b/kontor-echo/internal/repository/media_article.go new file mode 100644 index 0000000..5232a20 --- /dev/null +++ b/kontor-echo/internal/repository/media_article.go @@ -0,0 +1,85 @@ +package repository + +import ( + "context" + "fmt" + "kontor-api-echo/internal/models" + "log/slog" + "time" + + "github.com/labstack/echo/v4" + "github.com/uptrace/bun" +) + +type MediaArticleRepository struct { + db *bun.DB +} + +func (repository *MediaArticleRepository) Import(dtos models.MediaArticleDTOList) { + slog.Info("MediaArticleRepository#Import") + for index, dto := range dtos { + slog.Info("importing", "index", index, "profile", dto) + model := dto.ConvertDTOToModel() + existing_item := models.MediaArticle{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 NewMediaArticleRepository(db *bun.DB) *MediaArticleRepository { + repo := &MediaArticleRepository{db: db} + return repo +} + +func (repository *MediaArticleRepository) FindAll(context context.Context) ([]models.MediaArticle, error) { + var articles []models.MediaArticle + + err := repository.db.NewSelect().Model(&articles).Scan(context) + if err != nil { + slog.Info(err.Error()) + return nil, echo.ErrInternalServerError + } + slog.Info("MediaArticleRepository#FindAll", "count", len(articles)) + + return articles, nil +} + +func (repository *MediaArticleRepository) GetById(context context.Context, id string) (*models.MediaArticle, error) { + var article = models.MediaArticle{ID: id} + slog.Info("MediaArticleRepository#GetById", "id", id) + err := repository.db.NewSelect().Model(&article).Where("id = ?", id).Scan(context) + if err != nil { + slog.Info("MediaArticleRepository#GetById", "error", err.Error()) + return nil, err + } + return &article, err +} + +func (repository *MediaArticleRepository) Add(context context.Context, url string) (*models.MediaArticle, error) { + slog.Info("MediaArticleRepository#Add", "url", url) + return nil, fmt.Errorf("unimplemented method MediaArticleRepository#Add") +} + +func (repository *MediaArticleRepository) Delete(context context.Context, id string) error { + slog.Info("MediaArticleRepository#Delete", "id", id) + _, err := repository.db.NewDelete().Model((*models.MediaArticle)(nil)).Where("id = ?", id).Exec(context) + if err != nil { + slog.Info("MediaArticleRepository#Delete", "error", err.Error()) + } + return err +} diff --git a/kontor-echo/internal/repository/media_file.go b/kontor-echo/internal/repository/media_file.go new file mode 100644 index 0000000..e91842b --- /dev/null +++ b/kontor-echo/internal/repository/media_file.go @@ -0,0 +1,77 @@ +package repository + +import ( + "context" + "fmt" + "kontor-api-echo/internal/models" + "log/slog" + + "github.com/uptrace/bun" +) + +type MediaFileRepository struct { + db *bun.DB +} + +func (repository *MediaFileRepository) Import(dtos models.MediaFileDTOList) { + slog.Info("MediaFileRepository#Import") + for index, dto := range dtos { + 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 { + 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()) + } + } 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()) + } + } + } +} + +func NewMediaFileRepository(db *bun.DB) *MediaFileRepository { + repo := &MediaFileRepository{db: db} + return repo +} + +func (repository *MediaFileRepository) FindAll(context context.Context) ([]models.MediaFile, error) { + var files []models.MediaFile + + result := repository.db.Find(&files) + slog.Info("MediaFileRepository#FindAll", "count", result.RowsAffected) + + return files, nil +} + +func (repository *MediaFileRepository) GetById(context context.Context, id string) (*models.MediaFile, error) { + var file = 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 + } + return &file, result.Error +} + +func (repository *MediaFileRepository) Add(context context.Context, url string) (*models.MediaFile, error) { + slog.Info("MediaFileRepository#Add", "url", url) + return nil, fmt.Errorf("unimplemented method MediaFileRepository#Add") +} + +func (repository *MediaFileRepository) Delete(context context.Context, id string) error { + var file = models.MediaFile{ID: id} + slog.Info("MediaFileRepository#Delete", "id", id) + result := repository.db.Delete(&file) + if result.Error != nil { + slog.Info("MediaFileRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/repository/media_lofi.go b/kontor-echo/internal/repository/media_lofi.go new file mode 100644 index 0000000..7c4aacc --- /dev/null +++ b/kontor-echo/internal/repository/media_lofi.go @@ -0,0 +1,127 @@ +package repository + +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/uptrace/bun" +) + +type MediaLoFiRepository struct { + db *bun.DB +} + +func (repository *MediaLoFiRepository) Import(dtos models.MediaLoFiDTOList) { + slog.Info("MediaLoFiRepository#Import") + for index, dto := range dtos { + 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 { + 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()) + } + } 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()) + } + } + } +} + +func NewMediaLoFiRepository(db *bun.DB) *MediaLoFiRepository { + repo := &MediaLoFiRepository{db: db} + return repo +} + +func (repository *MediaLoFiRepository) FindAll(context context.Context) ([]models.MediaLoFi, error) { + var lofis []models.MediaLoFi + + result := repository.db.Find(&lofis) + slog.Info("MediaLoFiRepository#FindAll", "count", result.RowsAffected) + + return lofis, nil +} + +func (repository *MediaLoFiRepository) GetById(context context.Context, id string) (*models.MediaLoFi, error) { + var lofi = models.MediaLoFi{ID: id} + slog.Info("MediaLoFiRepository#GetById", "id", id) + result := repository.db.First(&lofi) + if result.Error != nil { + slog.Info("MediaLoFiRepository#GetById", "error", result.Error.Error()) + } + return &lofi, result.Error +} + +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) { + slog.Info("MediaLoFiRepository#Add URL not found", "url", webLink) + lofi = models.MediaLoFi{ + 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(&lofi) + if add_result.Error != nil { + slog.Info("add new MediaLofi", "error", add_result.Error) + return nil, add_result.Error + } + slog.Info("add new MediaLofi", "lofi", lofi) + return &lofi, 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} + 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 + } + lofi.Update(update) + repository.db.Save(&lofi) + return &lofi, nil +} + +func (repository *MediaLoFiRepository) Delete(context context.Context, id string) error { + var actor = models.MediaLoFi{ID: id} + slog.Info("MediaLoFiRepository#Delete", "id", id) + result := repository.db.Delete(&actor) + if result.Error != nil { + slog.Info("MediaLoFiRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/repository/media_music.go b/kontor-echo/internal/repository/media_music.go new file mode 100644 index 0000000..922e9de --- /dev/null +++ b/kontor-echo/internal/repository/media_music.go @@ -0,0 +1,127 @@ +package repository + +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/uptrace/bun" +) + +type MediaMusicRepository struct { + db *bun.DB +} + +func (repository *MediaMusicRepository) Import(dtos models.MediaMusicDTOList) { + slog.Info("MediaMusicRepository#Import") + for index, dto := range dtos { + 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 { + 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()) + } + } 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()) + } + } + } +} + +func NewMediaMusicRepository(db *bun.DB) *MediaMusicRepository { + repo := &MediaMusicRepository{db: db} + return repo +} + +func (repository *MediaMusicRepository) FindAll(context context.Context) ([]models.MediaMusic, error) { + var musics []models.MediaMusic + + result := repository.db.Find(&musics) + slog.Info("MediaMusicRepository#FindAll", "count", result.RowsAffected) + + return musics, nil +} + +func (repository *MediaMusicRepository) GetById(context context.Context, id string) (*models.MediaMusic, error) { + var music = 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()) + } + return &music, result.Error +} + +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) { + slog.Info("MediaMusicRepository#Add URL not found", "url", webLink) + music = models.MediaMusic{ + 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(&music) + if add_result.Error != nil { + slog.Info("add new MediaMusic", "error", add_result.Error) + return nil, add_result.Error + } + slog.Info("add new MediaMusic", "music", music) + return &music, 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 + } + music.Update(update) + repository.db.Save(&music) + return &music, nil +} + +func (repository *MediaMusicRepository) Delete(context context.Context, id string) error { + var actor = models.MediaMusic{ID: id} + slog.Info("MediaMusicRepository#Delete", "id", id) + result := repository.db.Delete(&actor) + if result.Error != nil { + slog.Info("MediaMusicRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/repository/media_video.go b/kontor-echo/internal/repository/media_video.go new file mode 100644 index 0000000..c45457b --- /dev/null +++ b/kontor-echo/internal/repository/media_video.go @@ -0,0 +1,127 @@ +package repository + +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/uptrace/bun" +) + +type MediaVideoRepository struct { + db *bun.DB +} + +func (repository *MediaVideoRepository) Import(dtos models.MediaVideoDTOList) { + slog.Info("MediaVideoRepository#Import") + for index, dto := range dtos { + slog.Info("importing", "index", index, "video", dto) + model := dto.ConvertDTOToModel() + existing_item := models.MediaVideo{ID: dto.ID} + result_existing := repository.db.First(&existing_item) + if result_existing.Error != 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()) + } + } 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()) + } + } + } +} + +func NewMediaVideoRepository(db *bun.DB) *MediaVideoRepository { + repo := &MediaVideoRepository{db: db} + return repo +} + +func (repository *MediaVideoRepository) FindAll(context context.Context) ([]models.MediaVideo, error) { + var videos []models.MediaVideo + + result := repository.db.Find(&videos) + slog.Info("MediaVideoRepository#FindAll", "count", result.RowsAffected) + + return videos, nil +} + +func (repository *MediaVideoRepository) GetById(context context.Context, id string) (*models.MediaVideo, error) { + var video = models.MediaVideo{ID: id} + slog.Info("MediaVideoRepository#GetById", "id", id) + result := repository.db.First(&video) + if result.Error != nil { + slog.Info("MediaVideoRepository#GetById", "error", result.Error.Error()) + } + return &video, result.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 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) Update(context context.Context, update models.MediaVideoDTO) (*models.MediaVideo, error) { + slog.Info("MediaVideoRepository#Update", "music", update) + var video = models.MediaVideo{ID: update.ID} + slog.Info("MediaVideoRepository#Update", "id", update.ID) + result := repository.db.First(&video) + if result.Error != nil { + slog.Info("MediaVideoRepository#Update", "error", result.Error.Error()) + return nil, result.Error + } + video.Update(update) + repository.db.Save(&video) + return &video, nil +} + +func (repository *MediaVideoRepository) Delete(context context.Context, id string) error { + var actor = models.MediaVideo{ID: id} + slog.Info("MediaVideoRepository#Delete", "id", id) + result := repository.db.Delete(&actor) + if result.Error != nil { + slog.Info("MediaVideoRepository#Delete", "error", result.Error.Error()) + } + return result.Error +} diff --git a/kontor-echo/internal/router/router.go b/kontor-echo/internal/router/router.go index 961c61d..82c4568 100644 --- a/kontor-echo/internal/router/router.go +++ b/kontor-echo/internal/router/router.go @@ -1,15 +1,17 @@ package router import ( - echojwt "github.com/labstack/echo-jwt/v5" + "kontor-api-echo/internal/handlers" + "log/slog" + "github.com/labstack/echo/v5" "github.com/labstack/echo/v5/middleware" ) -func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Router { +func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Echo { e := echo.New() - skipper := func(c echo.Context) bool { + skipper := func(c *echo.Context) bool { // Skip health check endpoint return c.Request().URL.Path == "/health" } @@ -17,14 +19,13 @@ func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Route e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogStatus: true, LogURI: true, - LogError: true, HandleError: true, Skipper: skipper, - LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { + 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()) + slog.Info("REQUEST-ERROR", "uri", v.URI, "status", v.Status, "err", v.Error.Error()) } return nil }, diff --git a/kontor-echo/internal/service/media_actor.go b/kontor-echo/internal/service/media_actor.go new file mode 100644 index 0000000..b13d690 --- /dev/null +++ b/kontor-echo/internal/service/media_actor.go @@ -0,0 +1,37 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaActorService struct { + repository *repository.MediaActorRepository +} + +func NewMediaActorService(repo *repository.MediaActorRepository) *MediaActorService { + service := &MediaActorService{repository: repo} + return service +} + +func (service *MediaActorService) List(context context.Context) ([]models.MediaActor, error) { + slog.Info("MediaActorService#List") + return service.repository.FindAll(context) +} + +func (service *MediaActorService) Get(context context.Context, id string) (*models.MediaActor, error) { + slog.Info("MediaActorService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaActorService) Add(context context.Context, url string) (*models.MediaActor, error) { + slog.Info("MediaActorService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaActorService) Delete(context context.Context, id string) error { + slog.Info("MediaActorService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_actor_file.go b/kontor-echo/internal/service/media_actor_file.go new file mode 100644 index 0000000..1373fb2 --- /dev/null +++ b/kontor-echo/internal/service/media_actor_file.go @@ -0,0 +1,37 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaActorFileService struct { + repository *repository.MediaActorFileRepository +} + +func NewMediaActorFileService(repo *repository.MediaActorFileRepository) *MediaActorFileService { + service := &MediaActorFileService{repository: repo} + return service +} + +func (service *MediaActorFileService) List(context context.Context) ([]models.MediaActorFile, error) { + slog.Info("MediaActorFileService#List") + return service.repository.FindAll(context) +} + +func (service *MediaActorFileService) Get(context context.Context, id string) (*models.MediaActorFile, error) { + slog.Info("MediaActorFileService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaActorFileService) Add(context context.Context, media_actor_id, media_file_id string) (*models.MediaActorFile, error) { + slog.Info("MediaActorFileService#Add") + return service.repository.Add(context, media_actor_id, media_file_id) +} + +func (service *MediaActorFileService) Delete(context context.Context, id string) error { + slog.Info("MediaActorFileService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_article.go b/kontor-echo/internal/service/media_article.go new file mode 100644 index 0000000..aca0612 --- /dev/null +++ b/kontor-echo/internal/service/media_article.go @@ -0,0 +1,37 @@ +package service + +import ( + "context" + "kontor-api-echo/internal/models" + "kontor-api-echo/internal/repository" + "log/slog" +) + +type MediaArticleService struct { + repository *repository.MediaArticleRepository +} + +func NewMediaArticleService(repo *repository.MediaArticleRepository) *MediaArticleService { + service := &MediaArticleService{repository: repo} + return service +} + +func (service *MediaArticleService) List(context context.Context) ([]models.MediaArticle, error) { + slog.Info("MediaArticleService#List") + return service.repository.FindAll(context) +} + +func (service *MediaArticleService) Get(context context.Context, id string) (*models.MediaArticle, error) { + slog.Info("MediaArticleService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaArticleService) Add(context context.Context, url string) (*models.MediaArticle, error) { + slog.Info("MediaArticleService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaArticleService) Delete(context context.Context, id string) error { + slog.Info("MediaArticleService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_file.go b/kontor-echo/internal/service/media_file.go new file mode 100644 index 0000000..af05bc8 --- /dev/null +++ b/kontor-echo/internal/service/media_file.go @@ -0,0 +1,37 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaFileService struct { + repository *repository.MediaFileRepository +} + +func NewMediaFileService(repo *repository.MediaFileRepository) *MediaFileService { + service := &MediaFileService{repository: repo} + return service +} + +func (service *MediaFileService) List(context context.Context) ([]models.MediaFile, error) { + slog.Info("MediaFileService#List") + return service.repository.FindAll(context) +} + +func (service *MediaFileService) Get(context context.Context, id string) (*models.MediaFile, error) { + slog.Info("MediaFileService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaFileService) Add(context context.Context, url string) (*models.MediaFile, error) { + slog.Info("MediaFileService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaFileService) Delete(context context.Context, id string) error { + slog.Info("MediaFileService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_lofi.go b/kontor-echo/internal/service/media_lofi.go new file mode 100644 index 0000000..b4bafb4 --- /dev/null +++ b/kontor-echo/internal/service/media_lofi.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaLoFiService struct { + repository *repository.MediaLoFiRepository +} + +func NewMediaLoFiService(repo *repository.MediaLoFiRepository) *MediaLoFiService { + service := &MediaLoFiService{repository: repo} + return service +} + +func (service *MediaLoFiService) List(context context.Context) ([]models.MediaLoFi, error) { + slog.Info("MediaLoFiService#List") + return service.repository.FindAll(context) +} + +func (service *MediaLoFiService) Get(context context.Context, id string) (*models.MediaLoFi, error) { + slog.Info("MediaLoFiService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaLoFiService) Add(context context.Context, url string) (*models.MediaLoFi, error) { + slog.Info("MediaLoFiService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaLoFiService) Update(context context.Context, lofi models.MediaLoFiDTO) (*models.MediaLoFi, error) { + slog.Info("MediaLoFiService#Update") + return service.repository.Update(context, lofi) +} + +func (service *MediaLoFiService) Delete(context context.Context, id string) error { + slog.Info("MediaLoFiService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_music.go b/kontor-echo/internal/service/media_music.go new file mode 100644 index 0000000..483aeba --- /dev/null +++ b/kontor-echo/internal/service/media_music.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaMusicService struct { + repository *repository.MediaMusicRepository +} + +func NewMediaMusicService(repo *repository.MediaMusicRepository) *MediaMusicService { + service := &MediaMusicService{repository: repo} + return service +} + +func (service *MediaMusicService) List(context context.Context) ([]models.MediaMusic, error) { + slog.Info("MediaMusicService#List") + return service.repository.FindAll(context) +} + +func (service *MediaMusicService) Get(context context.Context, id string) (*models.MediaMusic, error) { + slog.Info("MediaMusicService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaMusicService) Add(context context.Context, url string) (*models.MediaMusic, error) { + slog.Info("MediaMusicService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaMusicService) Update(context context.Context, music models.MediaMusicDTO) (*models.MediaMusic, error) { + slog.Info("MediaMusicService#Update") + return service.repository.Update(context, music) +} + +func (service *MediaMusicService) Delete(context context.Context, id string) error { + slog.Info("MediaMusicService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/internal/service/media_video.go b/kontor-echo/internal/service/media_video.go new file mode 100644 index 0000000..3ec28e0 --- /dev/null +++ b/kontor-echo/internal/service/media_video.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" +) + +type MediaVideoService struct { + repository *repository.MediaVideoRepository +} + +func NewMediaVideoService(repo *repository.MediaVideoRepository) *MediaVideoService { + service := &MediaVideoService{repository: repo} + return service +} + +func (service *MediaVideoService) List(context context.Context) ([]models.MediaVideo, error) { + slog.Info("MediaVideoService#List") + return service.repository.FindAll(context) +} + +func (service *MediaVideoService) Get(context context.Context, id string) (*models.MediaVideo, error) { + slog.Info("MediaVideoService#Get") + return service.repository.GetById(context, id) +} + +func (service *MediaVideoService) Add(context context.Context, url string) (*models.MediaVideo, error) { + slog.Info("MediaVideoService#Add") + return service.repository.Add(context, url) +} + +func (service *MediaVideoService) Update(context context.Context, music models.MediaVideoDTO) (*models.MediaVideo, error) { + slog.Info("MediaVideoService#Update") + return service.repository.Update(context, music) +} + +func (service *MediaVideoService) Delete(context context.Context, id string) error { + slog.Info("MediaVideoService#Delete") + return service.repository.Delete(context, id) +} diff --git a/kontor-echo/pkg/handlers/admin.go b/kontor-echo/pkg/handlers/admin.go deleted file mode 100644 index 71620d9..0000000 --- a/kontor-echo/pkg/handlers/admin.go +++ /dev/null @@ -1,30 +0,0 @@ -package handlers - -import ( - "github.com/uptrace/bun" -) - -type AdminHandler struct { - AuthHandler *AuthHandler - ProfileHandler *ProfileHandler - PermissionHandler *PermissionHandler - AssignmentHandler *AssignmentHandler - TokenHandler *TokenHandler - MailAccountHandler *MailAccountHandler - MailHandler *MailHandler - Secret []byte -} - -func NewAdminHandler(db *bun.DB, secret []byte) *AdminHandler { - adminHandler := &AdminHandler{ - AuthHandler: &AuthHandler{Service: service.NewAuthService(repository.NewProfileRepository(db), secret)}, - ProfileHandler: NewProfileHandler(db), - PermissionHandler: &PermissionHandler{Service: service.NewPermissionService(repository.NewPermissionRepository(db))}, - AssignmentHandler: NewAssignmentHandler(db), - TokenHandler: NewTokenHandler(db), - MailAccountHandler: NewMailAccountHandler(db), - MailHandler: NewMailHandler(db), - Secret: secret, - } - return adminHandler -} diff --git a/kontor-echo/pkg/router/router.go b/kontor-echo/pkg/router/router.go deleted file mode 100644 index 961c61d..0000000 --- a/kontor-echo/pkg/router/router.go +++ /dev/null @@ -1,33 +0,0 @@ -package router - -import ( - echojwt "github.com/labstack/echo-jwt/v5" - "github.com/labstack/echo/v5" - "github.com/labstack/echo/v5/middleware" -) - -func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Router { - e := echo.New() - - skipper := func(c echo.Context) bool { - // Skip health check endpoint - return c.Request().URL.Path == "/health" - } - - e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ - LogStatus: true, - LogURI: true, - LogError: true, - HandleError: true, - Skipper: skipper, - 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()) - } - return nil - }, - })) - return e -} diff --git a/kontor-echo/pkg/schema/media.go b/kontor-echo/pkg/schema/media.go deleted file mode 100644 index f2b5a4f..0000000 --- a/kontor-echo/pkg/schema/media.go +++ /dev/null @@ -1,79 +0,0 @@ -package schema - -import ( - "time" - - "github.com/uptrace/bun" -) - -type MediaFile struct { - bun.BaseModel `bun:"table:media_file"` - - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` - - MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_file_id"` -} - -type MediaActor struct { - bun.BaseModel `bun:"table:media_actor"` - - 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"` - Version int `bun:"version,default:0"` - Name string `bun:"name"` - WebLink string `bun:"url,unique:url"` - - MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_actor_id"` -} - -type MediaActorFile struct { - bun.BaseModel `bun:"table:media_actor_file"` - - 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"` - Version int `bun:"version,default:0"` - MediaActorID *string `bun:"media_actor_id"` - MediaActor *MediaActor `bun:"rel:belongs-to,join:media_actor_id=id"` - MediaFileID *string `bun:"media_file_id"` - MediaFile *MediaFile `bun:"rel:belongs-to,join:media_file_id=id"` -} - -type MediaArticle struct { - bun.BaseModel `bun:"table:media_article"` - - 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"` - Version int `bun:"version,default:0"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` -} - -type MediaVideo struct { - bun.BaseModel `bun:"table:media_article"` - - 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"` - Version int `bun:"version,default:0"` - CloudLink string `bun:"cloud_link"` - FileName string `bun:"file_name"` - Path string `bun:"path"` - Review bool `bun:"review"` - Title string `bun:"title"` - WebLink string `bun:"url,unique:url"` - ShouldDownload bool `bun:"should_download"` -}