Compare commits
7 Commits
25a0db9b1e
...
main
Author | SHA1 | Date | |
---|---|---|---|
cf82dede3b | |||
372dced0a1 | |||
a6570d463a | |||
7bbd8fc295 | |||
c9854d7e17 | |||
aa31d675bf | |||
c02d50c3ac |
@ -5,9 +5,9 @@ tmp_dir = "tmp"
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
cmd = "go build -o ./tmp/main ./cmd/api"
|
||||
delay = 1000
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata", "query"]
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go"]
|
||||
exclude_unchanged = false
|
||||
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
tmp
|
||||
|
||||
.env
|
||||
.env.local
|
9
.vscode/extensions.json
vendored
Normal file
9
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"usernamehw.errorlens",
|
||||
"golang.go",
|
||||
"sammycolon.go-builder-pattern-boilerplate",
|
||||
"fogio.inline-go-struct-tags-syntax-highlight",
|
||||
"templ-project.tpl-vscodium-golang"
|
||||
]
|
||||
}
|
74
cmd/api/main.go
Normal file
74
cmd/api/main.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/routers"
|
||||
"git.kocoder.xyz/kocoded/vt/utils"
|
||||
"github.com/gofiber/contrib/websocket"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
logger.Error("Error Loading Environment variables! ", "error", err)
|
||||
}
|
||||
|
||||
db := utils.SetupDatabase(os.Getenv("DB_DSN"), logger)
|
||||
|
||||
appCtx := utils.Application{Logger: logger, DB: db}
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
utils.RegisterMiddlewares(app)
|
||||
|
||||
utils.CreateOIDCClient(context.Background(), app, appCtx)
|
||||
|
||||
routers.RegisterMandantRouter(app.Group("/v1/mandant"), appCtx)
|
||||
routers.RegisterAnsprechpartnerRouter(app.Group("/v1/ansprechpartner"), appCtx)
|
||||
routers.RegisterFirmaRouter(app.Group("/v1/firma"), appCtx)
|
||||
|
||||
app.Use("/ws", func(c *fiber.Ctx) error {
|
||||
if websocket.IsWebSocketUpgrade(c) {
|
||||
c.Locals("allowed", true)
|
||||
return c.Next()
|
||||
}
|
||||
return fiber.ErrUpgradeRequired
|
||||
})
|
||||
|
||||
app.Get("/ws/:id<int>", websocket.New(func(c *websocket.Conn) {
|
||||
log.Println(c.Locals("allowed")) // true
|
||||
log.Println(c.Params("id")) // 123
|
||||
log.Println(c.Query("v")) // 1.0
|
||||
log.Println(c.Cookies("session")) // ""
|
||||
|
||||
var (
|
||||
mt int
|
||||
msg []byte
|
||||
err error
|
||||
)
|
||||
for {
|
||||
if mt, msg, err = c.ReadMessage(); err != nil {
|
||||
slog.Info("read", "error", err)
|
||||
break
|
||||
}
|
||||
|
||||
slog.Info("recv:", "messageType", mt, "bytes", msg)
|
||||
|
||||
if err = c.WriteMessage(mt, msg); err != nil {
|
||||
slog.Info("write", "error", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
log.Fatalln(app.Listen(":3000"))
|
||||
}
|
56
devfile.yaml
Normal file
56
devfile.yaml
Normal file
@ -0,0 +1,56 @@
|
||||
schemaVersion: 2.2.2
|
||||
metadata:
|
||||
name: vt
|
||||
displayName: VT
|
||||
description: VT-Backend
|
||||
icon: https://github.com/egonelbre/gophers/blob/master/icon/emoji/gopher-confused.png?raw=true
|
||||
tags:
|
||||
- Golang
|
||||
- Fiber
|
||||
- gorm
|
||||
projectType: go
|
||||
language: go
|
||||
version: 1.0.0
|
||||
starterProjects:
|
||||
- name: vt-backend
|
||||
git:
|
||||
checkoutFrom:
|
||||
remote: origin
|
||||
revision: main
|
||||
remotes:
|
||||
origin: https://git.kocoder.xyz/kocoded/vt
|
||||
components:
|
||||
- name: golang
|
||||
container:
|
||||
image: git.kocoder.xyz/diplomarbeit-absolventenverein/workspaces/universal:ubi9
|
||||
args: ["tail", "-f", "/dev/null"]
|
||||
mountSources: true
|
||||
endpoints:
|
||||
- name: http-go
|
||||
exposure: public
|
||||
targetPort: 3000
|
||||
commands:
|
||||
- id: build
|
||||
exec:
|
||||
workingDir: ${PROJECT_SOURCE}
|
||||
commandLine: kill $(pidof dotnet); dotnet build -c $CONFIGURATION $STARTUP_PROJECT /p:UseSharedCompilation=false
|
||||
component: dotnet
|
||||
group:
|
||||
isDefault: true
|
||||
kind: build
|
||||
- id: run
|
||||
exec:
|
||||
workingDir: ${PROJECT_SOURCE}
|
||||
commandLine: dotnet run -c $CONFIGURATION --no-build --project $STARTUP_PROJECT --no-launch-profile
|
||||
component: dotnet
|
||||
group:
|
||||
isDefault: true
|
||||
kind: run
|
||||
- id: release
|
||||
exec:
|
||||
workingDir: ${PROJECT_SOURCE}
|
||||
commandLine: dotnet build -c RELEASE Oqtane.sln && dotnet publish -c RELEASE Oqtane.Server/Oqtane.Server.csproj -o ./publish
|
||||
component: dotnet
|
||||
group:
|
||||
isDefault: true
|
||||
kind: deploy
|
11
go.mod
11
go.mod
@ -10,10 +10,20 @@ require (
|
||||
gorm.io/plugin/dbresolver v1.6.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fasthttp/websocket v1.5.8 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.28.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.15.0
|
||||
github.com/go-sql-driver/mysql v1.9.3 // indirect
|
||||
github.com/gofiber/contrib/websocket v1.3.4
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
@ -21,6 +31,7 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
|
16
go.sum
16
go.sum
@ -4,11 +4,19 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/coreos/go-oidc/v3 v3.15.0 h1:R6Oz8Z4bqWR7VFQ+sPSvZPQv4x8M+sJkDO5ojgwlyAg=
|
||||
github.com/coreos/go-oidc/v3 v3.15.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/fasthttp/websocket v1.5.8 h1:k5DpirKkftIF/w1R8ZzjSgARJrs54Je9YJK37DL/Ah8=
|
||||
github.com/fasthttp/websocket v1.5.8/go.mod h1:d08g8WaT6nnyvg9uMm8K9zMYyDjfKyj3170AtPRuVU0=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/gofiber/contrib/websocket v1.3.4 h1:tWeBdbJ8q0WFQXariLN4dBIbGH9KBU75s0s7YXplOSg=
|
||||
github.com/gofiber/contrib/websocket v1.3.4/go.mod h1:kTFBPC6YENCnKfKx0BoOFjgXxdz7E85/STdkmZPEmPs=
|
||||
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
|
||||
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
@ -31,6 +39,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
@ -59,6 +69,8 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@ -80,6 +92,10 @@ golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
113
main.go
113
main.go
@ -1,113 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"git.kocoder.xyz/kocoded/vt/query"
|
||||
"git.kocoder.xyz/kocoded/vt/routers"
|
||||
"git.kocoder.xyz/kocoded/vt/utils"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/compress"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/helmet"
|
||||
"github.com/gofiber/fiber/v2/middleware/idempotency"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/monitor"
|
||||
"github.com/gofiber/fiber/v2/middleware/pprof"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/gofiber/fiber/v2/middleware/requestid"
|
||||
"github.com/gofiber/fiber/v2/middleware/skip"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
SetupDatabase()
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
RegisterMiddlewares(app)
|
||||
|
||||
routers.RegisterAnsprechpartnerRouter(app.Group("/v1/ansprechpartner"), logger)
|
||||
routers.RegisterFirmaRouter(app.Group("/v1/firma"), logger)
|
||||
|
||||
log.Fatalln(app.Listen(":3000"))
|
||||
}
|
||||
|
||||
func RegisterMiddlewares(app *fiber.App) {
|
||||
app.Use(requestid.New())
|
||||
app.Use(compress.New())
|
||||
app.Use(helmet.New())
|
||||
app.Use(cors.New())
|
||||
// app.Use(csrf.New())
|
||||
// app.Use(healthcheck.New(healthcheck.Config{}))
|
||||
app.Use(idempotency.New())
|
||||
// app.Use(limiter.New())
|
||||
app.Use(logger.New())
|
||||
app.Use("/dbg/monitor", monitor.New())
|
||||
app.Use(pprof.New())
|
||||
app.Use(recover.New())
|
||||
app.Use(skip.New(AddPaginationParams, func(c *fiber.Ctx) bool {
|
||||
return c.Method() != fiber.MethodGet
|
||||
}))
|
||||
}
|
||||
|
||||
func AddPaginationParams(c *fiber.Ctx) error {
|
||||
err := c.Next()
|
||||
if err != nil {
|
||||
var offset *utils.OffsetPaginationError
|
||||
if errors.As(err, &offset) {
|
||||
c.Append("X-Page", strconv.Itoa(offset.Page))
|
||||
c.Append("X-Pages", strconv.Itoa(offset.Pages))
|
||||
c.Append("X-Next-Page", strconv.Itoa(offset.NextPage))
|
||||
c.Append("X-Last-Page", strconv.Itoa(offset.LastPage))
|
||||
return nil
|
||||
}
|
||||
|
||||
var keyset *utils.KeysetPaginationError
|
||||
if errors.As(err, &keyset) {
|
||||
c.Append("X-Key", strconv.Itoa(keyset.Key))
|
||||
c.Append("X-Previous-Key", strconv.Itoa(keyset.PreviousKey))
|
||||
c.Append("X-Next-Key", strconv.Itoa(keyset.NextKey))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func SetupDatabase() {
|
||||
dsn := "host=10.1.0.2 user=vt password=20a1c7809cd065bc5afe7c36fde26abf625316c8a83cc841b435c9acf3619b1f dbname=vt port=5432 sslmode=prefer TimeZone=Europe/Vienna"
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.SetupJoinTable(model.Ansprechpartner{}, "Firmen", model.FirmaAnsprechpartner{})
|
||||
db.SetupJoinTable(model.Firma{}, "Ansprechpartner", model.FirmaAnsprechpartner{})
|
||||
|
||||
db.AutoMigrate(&model.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{})
|
||||
|
||||
g := gen.NewGenerator(gen.Config{
|
||||
OutPath: "./query",
|
||||
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
|
||||
})
|
||||
|
||||
// gormdb, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
|
||||
g.UseDB(db) // reuse your gorm db
|
||||
|
||||
// Generate basic type-safe DAO API for struct `model.User` following conventions
|
||||
g.ApplyBasic(model.Ansprechpartner{}, model.Dokument{}, model.Firma{}, model.Kalender{}, model.Kalendereintrag{}, model.Kostenstelle{}, model.Lager{}, model.Lagerplatz{}, model.Material{}, model.Nachricht{}, model.Projekt{}, model.Rechnung{}, model.Rechnungsposition{}, model.Scanobject{}, model.User{}, model.Zahlung{}, model.FirmaAnsprechpartner{})
|
||||
|
||||
// Generate the code
|
||||
g.Execute()
|
||||
|
||||
query.SetDefault(db)
|
||||
}
|
11
model/mandant.go
Normal file
11
model/mandant.go
Normal file
@ -0,0 +1,11 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"git.kocoder.xyz/kocoded/vt/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Mandant struct {
|
||||
gorm.Model
|
||||
types.Mandant
|
||||
}
|
@ -4,4 +4,6 @@ import "gorm.io/gorm"
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Sub string `json:"sub" gorm:"unique"`
|
||||
Email string
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ var (
|
||||
Kostenstelle *kostenstelle
|
||||
Lager *lager
|
||||
Lagerplatz *lagerplatz
|
||||
Mandant *mandant
|
||||
Material *material
|
||||
Nachricht *nachricht
|
||||
Projekt *projekt
|
||||
@ -47,6 +48,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
Kostenstelle = &Q.Kostenstelle
|
||||
Lager = &Q.Lager
|
||||
Lagerplatz = &Q.Lagerplatz
|
||||
Mandant = &Q.Mandant
|
||||
Material = &Q.Material
|
||||
Nachricht = &Q.Nachricht
|
||||
Projekt = &Q.Projekt
|
||||
@ -69,6 +71,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
Kostenstelle: newKostenstelle(db, opts...),
|
||||
Lager: newLager(db, opts...),
|
||||
Lagerplatz: newLagerplatz(db, opts...),
|
||||
Mandant: newMandant(db, opts...),
|
||||
Material: newMaterial(db, opts...),
|
||||
Nachricht: newNachricht(db, opts...),
|
||||
Projekt: newProjekt(db, opts...),
|
||||
@ -92,6 +95,7 @@ type Query struct {
|
||||
Kostenstelle kostenstelle
|
||||
Lager lager
|
||||
Lagerplatz lagerplatz
|
||||
Mandant mandant
|
||||
Material material
|
||||
Nachricht nachricht
|
||||
Projekt projekt
|
||||
@ -116,6 +120,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
|
||||
Kostenstelle: q.Kostenstelle.clone(db),
|
||||
Lager: q.Lager.clone(db),
|
||||
Lagerplatz: q.Lagerplatz.clone(db),
|
||||
Mandant: q.Mandant.clone(db),
|
||||
Material: q.Material.clone(db),
|
||||
Nachricht: q.Nachricht.clone(db),
|
||||
Projekt: q.Projekt.clone(db),
|
||||
@ -147,6 +152,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
||||
Kostenstelle: q.Kostenstelle.replaceDB(db),
|
||||
Lager: q.Lager.replaceDB(db),
|
||||
Lagerplatz: q.Lagerplatz.replaceDB(db),
|
||||
Mandant: q.Mandant.replaceDB(db),
|
||||
Material: q.Material.replaceDB(db),
|
||||
Nachricht: q.Nachricht.replaceDB(db),
|
||||
Projekt: q.Projekt.replaceDB(db),
|
||||
@ -168,6 +174,7 @@ type queryCtx struct {
|
||||
Kostenstelle IKostenstelleDo
|
||||
Lager ILagerDo
|
||||
Lagerplatz ILagerplatzDo
|
||||
Mandant IMandantDo
|
||||
Material IMaterialDo
|
||||
Nachricht INachrichtDo
|
||||
Projekt IProjektDo
|
||||
@ -189,6 +196,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
Kostenstelle: q.Kostenstelle.WithContext(ctx),
|
||||
Lager: q.Lager.WithContext(ctx),
|
||||
Lagerplatz: q.Lagerplatz.WithContext(ctx),
|
||||
Mandant: q.Mandant.WithContext(ctx),
|
||||
Material: q.Material.WithContext(ctx),
|
||||
Nachricht: q.Nachricht.WithContext(ctx),
|
||||
Projekt: q.Projekt.WithContext(ctx),
|
||||
|
411
query/mandants.gen.go
Normal file
411
query/mandants.gen.go
Normal file
@ -0,0 +1,411 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
)
|
||||
|
||||
func newMandant(db *gorm.DB, opts ...gen.DOOption) mandant {
|
||||
_mandant := mandant{}
|
||||
|
||||
_mandant.mandantDo.UseDB(db, opts...)
|
||||
_mandant.mandantDo.UseModel(&model.Mandant{})
|
||||
|
||||
tableName := _mandant.mandantDo.TableName()
|
||||
_mandant.ALL = field.NewAsterisk(tableName)
|
||||
_mandant.ID = field.NewUint(tableName, "id")
|
||||
_mandant.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_mandant.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_mandant.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_mandant.Name = field.NewString(tableName, "name")
|
||||
_mandant.Logo = field.NewString(tableName, "logo")
|
||||
_mandant.Plan = field.NewString(tableName, "plan")
|
||||
_mandant.Color = field.NewString(tableName, "color")
|
||||
|
||||
_mandant.fillFieldMap()
|
||||
|
||||
return _mandant
|
||||
}
|
||||
|
||||
type mandant struct {
|
||||
mandantDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Uint
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Name field.String
|
||||
Logo field.String
|
||||
Plan field.String
|
||||
Color field.String
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (m mandant) Table(newTableName string) *mandant {
|
||||
m.mandantDo.UseTable(newTableName)
|
||||
return m.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (m mandant) As(alias string) *mandant {
|
||||
m.mandantDo.DO = *(m.mandantDo.As(alias).(*gen.DO))
|
||||
return m.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (m *mandant) updateTableName(table string) *mandant {
|
||||
m.ALL = field.NewAsterisk(table)
|
||||
m.ID = field.NewUint(table, "id")
|
||||
m.CreatedAt = field.NewTime(table, "created_at")
|
||||
m.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
m.DeletedAt = field.NewField(table, "deleted_at")
|
||||
m.Name = field.NewString(table, "name")
|
||||
m.Logo = field.NewString(table, "logo")
|
||||
m.Plan = field.NewString(table, "plan")
|
||||
m.Color = field.NewString(table, "color")
|
||||
|
||||
m.fillFieldMap()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *mandant) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := m.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (m *mandant) fillFieldMap() {
|
||||
m.fieldMap = make(map[string]field.Expr, 8)
|
||||
m.fieldMap["id"] = m.ID
|
||||
m.fieldMap["created_at"] = m.CreatedAt
|
||||
m.fieldMap["updated_at"] = m.UpdatedAt
|
||||
m.fieldMap["deleted_at"] = m.DeletedAt
|
||||
m.fieldMap["name"] = m.Name
|
||||
m.fieldMap["logo"] = m.Logo
|
||||
m.fieldMap["plan"] = m.Plan
|
||||
m.fieldMap["color"] = m.Color
|
||||
}
|
||||
|
||||
func (m mandant) clone(db *gorm.DB) mandant {
|
||||
m.mandantDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m mandant) replaceDB(db *gorm.DB) mandant {
|
||||
m.mandantDo.ReplaceDB(db)
|
||||
return m
|
||||
}
|
||||
|
||||
type mandantDo struct{ gen.DO }
|
||||
|
||||
type IMandantDo interface {
|
||||
gen.SubQuery
|
||||
Debug() IMandantDo
|
||||
WithContext(ctx context.Context) IMandantDo
|
||||
WithResult(fc func(tx gen.Dao)) gen.ResultInfo
|
||||
ReplaceDB(db *gorm.DB)
|
||||
ReadDB() IMandantDo
|
||||
WriteDB() IMandantDo
|
||||
As(alias string) gen.Dao
|
||||
Session(config *gorm.Session) IMandantDo
|
||||
Columns(cols ...field.Expr) gen.Columns
|
||||
Clauses(conds ...clause.Expression) IMandantDo
|
||||
Not(conds ...gen.Condition) IMandantDo
|
||||
Or(conds ...gen.Condition) IMandantDo
|
||||
Select(conds ...field.Expr) IMandantDo
|
||||
Where(conds ...gen.Condition) IMandantDo
|
||||
Order(conds ...field.Expr) IMandantDo
|
||||
Distinct(cols ...field.Expr) IMandantDo
|
||||
Omit(cols ...field.Expr) IMandantDo
|
||||
Join(table schema.Tabler, on ...field.Expr) IMandantDo
|
||||
LeftJoin(table schema.Tabler, on ...field.Expr) IMandantDo
|
||||
RightJoin(table schema.Tabler, on ...field.Expr) IMandantDo
|
||||
Group(cols ...field.Expr) IMandantDo
|
||||
Having(conds ...gen.Condition) IMandantDo
|
||||
Limit(limit int) IMandantDo
|
||||
Offset(offset int) IMandantDo
|
||||
Count() (count int64, err error)
|
||||
Scopes(funcs ...func(gen.Dao) gen.Dao) IMandantDo
|
||||
Unscoped() IMandantDo
|
||||
Create(values ...*model.Mandant) error
|
||||
CreateInBatches(values []*model.Mandant, batchSize int) error
|
||||
Save(values ...*model.Mandant) error
|
||||
First() (*model.Mandant, error)
|
||||
Take() (*model.Mandant, error)
|
||||
Last() (*model.Mandant, error)
|
||||
Find() ([]*model.Mandant, error)
|
||||
FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Mandant, err error)
|
||||
FindInBatches(result *[]*model.Mandant, batchSize int, fc func(tx gen.Dao, batch int) error) error
|
||||
Pluck(column field.Expr, dest interface{}) error
|
||||
Delete(...*model.Mandant) (info gen.ResultInfo, err error)
|
||||
Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
Updates(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
|
||||
UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
|
||||
UpdateFrom(q gen.SubQuery) gen.Dao
|
||||
Attrs(attrs ...field.AssignExpr) IMandantDo
|
||||
Assign(attrs ...field.AssignExpr) IMandantDo
|
||||
Joins(fields ...field.RelationField) IMandantDo
|
||||
Preload(fields ...field.RelationField) IMandantDo
|
||||
FirstOrInit() (*model.Mandant, error)
|
||||
FirstOrCreate() (*model.Mandant, error)
|
||||
FindByPage(offset int, limit int) (result []*model.Mandant, count int64, err error)
|
||||
ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
|
||||
Rows() (*sql.Rows, error)
|
||||
Row() *sql.Row
|
||||
Scan(result interface{}) (err error)
|
||||
Returning(value interface{}, columns ...string) IMandantDo
|
||||
UnderlyingDB() *gorm.DB
|
||||
schema.Tabler
|
||||
}
|
||||
|
||||
func (m mandantDo) Debug() IMandantDo {
|
||||
return m.withDO(m.DO.Debug())
|
||||
}
|
||||
|
||||
func (m mandantDo) WithContext(ctx context.Context) IMandantDo {
|
||||
return m.withDO(m.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (m mandantDo) ReadDB() IMandantDo {
|
||||
return m.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (m mandantDo) WriteDB() IMandantDo {
|
||||
return m.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (m mandantDo) Session(config *gorm.Session) IMandantDo {
|
||||
return m.withDO(m.DO.Session(config))
|
||||
}
|
||||
|
||||
func (m mandantDo) Clauses(conds ...clause.Expression) IMandantDo {
|
||||
return m.withDO(m.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Returning(value interface{}, columns ...string) IMandantDo {
|
||||
return m.withDO(m.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Not(conds ...gen.Condition) IMandantDo {
|
||||
return m.withDO(m.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Or(conds ...gen.Condition) IMandantDo {
|
||||
return m.withDO(m.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Select(conds ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Where(conds ...gen.Condition) IMandantDo {
|
||||
return m.withDO(m.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Order(conds ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Distinct(cols ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Omit(cols ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Join(table schema.Tabler, on ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (m mandantDo) LeftJoin(table schema.Tabler, on ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (m mandantDo) RightJoin(table schema.Tabler, on ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Group(cols ...field.Expr) IMandantDo {
|
||||
return m.withDO(m.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Having(conds ...gen.Condition) IMandantDo {
|
||||
return m.withDO(m.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Limit(limit int) IMandantDo {
|
||||
return m.withDO(m.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (m mandantDo) Offset(offset int) IMandantDo {
|
||||
return m.withDO(m.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (m mandantDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IMandantDo {
|
||||
return m.withDO(m.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Unscoped() IMandantDo {
|
||||
return m.withDO(m.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (m mandantDo) Create(values ...*model.Mandant) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return m.DO.Create(values)
|
||||
}
|
||||
|
||||
func (m mandantDo) CreateInBatches(values []*model.Mandant, batchSize int) error {
|
||||
return m.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (m mandantDo) Save(values ...*model.Mandant) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return m.DO.Save(values)
|
||||
}
|
||||
|
||||
func (m mandantDo) First() (*model.Mandant, error) {
|
||||
if result, err := m.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Mandant), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m mandantDo) Take() (*model.Mandant, error) {
|
||||
if result, err := m.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Mandant), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m mandantDo) Last() (*model.Mandant, error) {
|
||||
if result, err := m.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Mandant), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m mandantDo) Find() ([]*model.Mandant, error) {
|
||||
result, err := m.DO.Find()
|
||||
return result.([]*model.Mandant), err
|
||||
}
|
||||
|
||||
func (m mandantDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Mandant, err error) {
|
||||
buf := make([]*model.Mandant, 0, batchSize)
|
||||
err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (m mandantDo) FindInBatches(result *[]*model.Mandant, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return m.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (m mandantDo) Attrs(attrs ...field.AssignExpr) IMandantDo {
|
||||
return m.withDO(m.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Assign(attrs ...field.AssignExpr) IMandantDo {
|
||||
return m.withDO(m.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (m mandantDo) Joins(fields ...field.RelationField) IMandantDo {
|
||||
for _, _f := range fields {
|
||||
m = *m.withDO(m.DO.Joins(_f))
|
||||
}
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m mandantDo) Preload(fields ...field.RelationField) IMandantDo {
|
||||
for _, _f := range fields {
|
||||
m = *m.withDO(m.DO.Preload(_f))
|
||||
}
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m mandantDo) FirstOrInit() (*model.Mandant, error) {
|
||||
if result, err := m.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Mandant), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m mandantDo) FirstOrCreate() (*model.Mandant, error) {
|
||||
if result, err := m.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Mandant), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m mandantDo) FindByPage(offset int, limit int) (result []*model.Mandant, count int64, err error) {
|
||||
result, err = m.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = m.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (m mandantDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = m.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = m.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (m mandantDo) Scan(result interface{}) (err error) {
|
||||
return m.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (m mandantDo) Delete(models ...*model.Mandant) (result gen.ResultInfo, err error) {
|
||||
return m.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (m *mandantDo) withDO(do gen.Dao) *mandantDo {
|
||||
m.DO = *do.(*gen.DO)
|
||||
return m
|
||||
}
|
@ -32,6 +32,8 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user {
|
||||
_user.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_user.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_user.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_user.Sub = field.NewString(tableName, "sub")
|
||||
_user.Email = field.NewString(tableName, "email")
|
||||
|
||||
_user.fillFieldMap()
|
||||
|
||||
@ -46,6 +48,8 @@ type user struct {
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Sub field.String
|
||||
Email field.String
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@ -66,6 +70,8 @@ func (u *user) updateTableName(table string) *user {
|
||||
u.CreatedAt = field.NewTime(table, "created_at")
|
||||
u.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
u.DeletedAt = field.NewField(table, "deleted_at")
|
||||
u.Sub = field.NewString(table, "sub")
|
||||
u.Email = field.NewString(table, "email")
|
||||
|
||||
u.fillFieldMap()
|
||||
|
||||
@ -82,11 +88,13 @@ func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
}
|
||||
|
||||
func (u *user) fillFieldMap() {
|
||||
u.fieldMap = make(map[string]field.Expr, 4)
|
||||
u.fieldMap = make(map[string]field.Expr, 6)
|
||||
u.fieldMap["id"] = u.ID
|
||||
u.fieldMap["created_at"] = u.CreatedAt
|
||||
u.fieldMap["updated_at"] = u.UpdatedAt
|
||||
u.fieldMap["deleted_at"] = u.DeletedAt
|
||||
u.fieldMap["sub"] = u.Sub
|
||||
u.fieldMap["email"] = u.Email
|
||||
}
|
||||
|
||||
func (u user) clone(db *gorm.DB) user {
|
||||
|
@ -1,19 +1,18 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"git.kocoder.xyz/kocoded/vt/query"
|
||||
"git.kocoder.xyz/kocoded/vt/utils"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type ansprechpartnerRouter struct {
|
||||
logger *slog.Logger
|
||||
utils.Application
|
||||
}
|
||||
|
||||
func RegisterAnsprechpartnerRouter(group fiber.Router, logger *slog.Logger) {
|
||||
router := &ansprechpartnerRouter{logger: logger}
|
||||
func RegisterAnsprechpartnerRouter(group fiber.Router, appCtx utils.Application) {
|
||||
router := &ansprechpartnerRouter{Application: appCtx}
|
||||
|
||||
group.Post("/new", router.createAnsprechpartner)
|
||||
group.Get("/all", router.getAllAnsprechpartners)
|
||||
|
@ -1,19 +1,18 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"git.kocoder.xyz/kocoded/vt/query"
|
||||
"git.kocoder.xyz/kocoded/vt/utils"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type firmaRouter struct {
|
||||
logger *slog.Logger
|
||||
utils.Application
|
||||
}
|
||||
|
||||
func RegisterFirmaRouter(group fiber.Router, logger *slog.Logger) {
|
||||
router := &firmaRouter{logger: logger}
|
||||
func RegisterFirmaRouter(group fiber.Router, appCtx utils.Application) {
|
||||
router := &firmaRouter{Application: appCtx}
|
||||
|
||||
group.Post("/new", router.createFirma)
|
||||
group.Get("/all", router.getAllFirmen)
|
||||
|
64
routers/mandant.go
Normal file
64
routers/mandant.go
Normal file
@ -0,0 +1,64 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"git.kocoder.xyz/kocoded/vt/query"
|
||||
"git.kocoder.xyz/kocoded/vt/utils"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type mandantRouter struct {
|
||||
utils.Application
|
||||
currentMandant uint
|
||||
}
|
||||
|
||||
func RegisterMandantRouter(group fiber.Router, appCtx utils.Application) {
|
||||
router := &mandantRouter{currentMandant: 1, Application: appCtx}
|
||||
|
||||
group.Get("/current", router.getCurrentMandant)
|
||||
group.Put("/current", router.setCurrentMandant)
|
||||
group.Get("/all", router.getAllMandant)
|
||||
}
|
||||
|
||||
func (r *mandantRouter) getCurrentMandant(c *fiber.Ctx) error {
|
||||
m := query.Mandant
|
||||
|
||||
currentMandant, err := m.Where(m.ID.Eq(r.currentMandant)).First()
|
||||
if err != nil {
|
||||
r.Logger.Warn("Current mandant not found.", "error", err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return c.JSON(currentMandant)
|
||||
}
|
||||
|
||||
func (r *mandantRouter) getAllMandant(c *fiber.Ctx) error {
|
||||
m := query.Mandant
|
||||
|
||||
mandanten, err := m.Find()
|
||||
if err != nil {
|
||||
r.Logger.Warn("Current mandant not found.", "error", err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return c.JSON(mandanten)
|
||||
}
|
||||
|
||||
func (r *mandantRouter) setCurrentMandant(c *fiber.Ctx) error {
|
||||
m := query.Mandant
|
||||
mandant := &model.Mandant{}
|
||||
|
||||
if err := c.BodyParser(mandant); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.currentMandant = mandant.ID
|
||||
|
||||
currentMandant, err := m.Where(m.ID.Eq(r.currentMandant)).First()
|
||||
if err != nil {
|
||||
r.Logger.Warn("Current mandant not found.", "error", err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return c.JSON(currentMandant)
|
||||
}
|
@ -1 +0,0 @@
|
||||
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
9
types/mandant.go
Normal file
9
types/mandant.go
Normal file
@ -0,0 +1,9 @@
|
||||
package types
|
||||
|
||||
type Mandant struct {
|
||||
// ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Logo string `json:"logo"`
|
||||
Plan string `json:"plan"`
|
||||
Color string `json:"color"`
|
||||
}
|
20
utils/applicationCtx.go
Normal file
20
utils/applicationCtx.go
Normal file
@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
Logger *slog.Logger
|
||||
DB *gorm.DB
|
||||
ActiveSessions []Session
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
Token string
|
||||
UserID uint
|
||||
CreatedAt time.Time
|
||||
}
|
140
utils/authentication.go
Normal file
140
utils/authentication.go
Normal file
@ -0,0 +1,140 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) {
|
||||
setCallbackCookieExp(w, r, name, value, int(time.Hour.Seconds()))
|
||||
}
|
||||
|
||||
func setCallbackCookieExp(w http.ResponseWriter, r *http.Request, name, value string, maxAge int) {
|
||||
c := &http.Cookie{
|
||||
Name: name,
|
||||
Value: value,
|
||||
Path: "/",
|
||||
MaxAge: maxAge,
|
||||
Secure: r.TLS != nil,
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, c)
|
||||
}
|
||||
|
||||
func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
|
||||
provider, err := oidc.NewProvider(ctx, "https://keycloak.kocoder.xyz/realms/che")
|
||||
if err != nil {
|
||||
appCtx.Logger.Error("Error generating OIDC Provider. ", "error", err)
|
||||
}
|
||||
|
||||
oauthConfig := oauth2.Config{
|
||||
ClientID: os.Getenv("CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("CLIENT_SECRET"),
|
||||
RedirectURL: "http://localhost:3000/api/auth/callback",
|
||||
|
||||
Endpoint: provider.Endpoint(),
|
||||
|
||||
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess, "profile", "email"},
|
||||
}
|
||||
|
||||
app.Get("/api/auth", adaptor.HTTPHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
state, err := RandString(16)
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("Unable to create a state", "error", err)
|
||||
http.Error(w, "Unable to create a state", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
setCallbackCookie(w, r, "state", state)
|
||||
|
||||
http.Redirect(w, r, oauthConfig.AuthCodeURL(state), http.StatusFound)
|
||||
}))
|
||||
|
||||
app.Get("/api/auth/callback", adaptor.HTTPHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
state, err := r.Cookie("state")
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("State cookie not found", "error", err)
|
||||
http.Error(w, "state not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Query().Get("state") != state.Value {
|
||||
appCtx.Logger.Warn("State cookie and header not matching", "error", err)
|
||||
http.Error(w, "states not matching", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := oauthConfig.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("Failed to exchange token", "error", err)
|
||||
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(oauth2Token))
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("failed to get userinfo", "error", err)
|
||||
http.Error(w, "Failed to get userinfo: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
resp := struct {
|
||||
Token *oauth2.Token
|
||||
UserInfo *oidc.UserInfo
|
||||
}{oauth2Token, userInfo}
|
||||
|
||||
data, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("Failed to parse JSON", "error", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
user := &model.User{}
|
||||
if appCtx.DB.Where(model.User{Email: resp.UserInfo.Email}).Assign(model.User{Sub: resp.UserInfo.Subject}).FirstOrCreate(user).Error != nil {
|
||||
appCtx.Logger.Warn("Failed to create user in DB")
|
||||
http.Error(w, "failed to create user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
setCallbackCookieExp(w, r, "state", "", -1)
|
||||
|
||||
cookie, err := RandString(24)
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("Couldn't generate session-cookie.")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
setCallbackCookieExp(w, r, "auth-cookie", cookie, int(time.Hour.Seconds()))
|
||||
appCtx.ActiveSessions = append(appCtx.ActiveSessions, Session{Token: cookie, UserID: user.ID, CreatedAt: time.Now()})
|
||||
|
||||
http.Redirect(w, r, "http://localhost:3001", http.StatusFound)
|
||||
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
appCtx.Logger.Error("Unable to send response", "error", err)
|
||||
}
|
||||
}))
|
||||
|
||||
app.Get("/api/auth/currentSession", func(c *fiber.Ctx) error {
|
||||
authToken := c.Cookies("auth-cookie")
|
||||
|
||||
sessionId := slices.IndexFunc(appCtx.ActiveSessions, func(s Session) bool {
|
||||
return s.Token == authToken
|
||||
})
|
||||
|
||||
session := appCtx.ActiveSessions[sessionId]
|
||||
|
||||
return c.JSON(session)
|
||||
})
|
||||
}
|
49
utils/db.go
Normal file
49
utils/db.go
Normal file
@ -0,0 +1,49 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"git.kocoder.xyz/kocoded/vt/query"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func SetupDatabase(dsn string, logger *slog.Logger) *gorm.DB {
|
||||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
logger.Error("Error connecting to the Database", "error", err)
|
||||
}
|
||||
|
||||
err = db.SetupJoinTable(model.Ansprechpartner{}, "Firmen", model.FirmaAnsprechpartner{})
|
||||
if err != nil {
|
||||
logger.Error("Error setting up Join Tables", "error", err)
|
||||
}
|
||||
err = db.SetupJoinTable(model.Firma{}, "Ansprechpartner", model.FirmaAnsprechpartner{})
|
||||
if err != nil {
|
||||
logger.Error("Error setting up Join Tables", "error", err)
|
||||
}
|
||||
err = db.AutoMigrate(&model.Mandant{}, &model.User{}, &model.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{})
|
||||
if err != nil {
|
||||
logger.Error("Error setting up Join Tables", "error", err)
|
||||
}
|
||||
|
||||
g := gen.NewGenerator(gen.Config{
|
||||
OutPath: "./query",
|
||||
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
|
||||
})
|
||||
|
||||
// gormdb, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
|
||||
g.UseDB(db) // reuse your gorm db
|
||||
|
||||
// Generate basic type-safe DAO API for struct `model.User` following conventions
|
||||
g.ApplyBasic(model.Mandant{}, model.User{}, model.Ansprechpartner{}, model.Dokument{}, model.Firma{}, model.Kalender{}, model.Kalendereintrag{}, model.Kostenstelle{}, model.Lager{}, model.Lagerplatz{}, model.Material{}, model.Nachricht{}, model.Projekt{}, model.Rechnung{}, model.Rechnungsposition{}, model.Scanobject{}, model.User{}, model.Zahlung{}, model.FirmaAnsprechpartner{})
|
||||
|
||||
// Generate the code
|
||||
g.Execute()
|
||||
|
||||
query.SetDefault(db)
|
||||
|
||||
return db
|
||||
}
|
36
utils/middleware.go
Normal file
36
utils/middleware.go
Normal file
@ -0,0 +1,36 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/compress"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/helmet"
|
||||
"github.com/gofiber/fiber/v2/middleware/idempotency"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/monitor"
|
||||
"github.com/gofiber/fiber/v2/middleware/pprof"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
"github.com/gofiber/fiber/v2/middleware/requestid"
|
||||
"github.com/gofiber/fiber/v2/middleware/skip"
|
||||
)
|
||||
|
||||
func RegisterMiddlewares(app *fiber.App) {
|
||||
app.Use(requestid.New())
|
||||
app.Use(compress.New())
|
||||
app.Use(helmet.New())
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowOrigins: "http://localhost:3000, http://localhost:3001",
|
||||
AllowCredentials: true,
|
||||
}))
|
||||
// app.Use(csrf.New())
|
||||
// app.Use(healthcheck.New(healthcheck.Config{}))
|
||||
app.Use(idempotency.New())
|
||||
// app.Use(limiter.New())
|
||||
app.Use(logger.New())
|
||||
app.Use("/dbg/monitor", monitor.New())
|
||||
app.Use(pprof.New())
|
||||
app.Use(recover.New())
|
||||
app.Use(skip.New(AddPaginationParams, func(c *fiber.Ctx) bool {
|
||||
return c.Method() != fiber.MethodGet
|
||||
}))
|
||||
}
|
@ -1,5 +1,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type OffsetPaginationError struct {
|
||||
Page int
|
||||
Pages int
|
||||
@ -35,3 +42,27 @@ func (p *KeysetPaginationError) Error() string {
|
||||
func NewKeysetPaginationError(key int, next int, previous int) error {
|
||||
return &KeysetPaginationError{Key: key, NextKey: next, PreviousKey: previous}
|
||||
}
|
||||
|
||||
func AddPaginationParams(c *fiber.Ctx) error {
|
||||
err := c.Next()
|
||||
if err != nil {
|
||||
|
||||
var offset *OffsetPaginationError
|
||||
if errors.As(err, &offset) {
|
||||
c.Append("X-Page", strconv.Itoa(offset.Page))
|
||||
c.Append("X-Pages", strconv.Itoa(offset.Pages))
|
||||
c.Append("X-Next-Page", strconv.Itoa(offset.NextPage))
|
||||
c.Append("X-Last-Page", strconv.Itoa(offset.LastPage))
|
||||
return nil
|
||||
}
|
||||
|
||||
var keyset *KeysetPaginationError
|
||||
if errors.As(err, &keyset) {
|
||||
c.Append("X-Key", strconv.Itoa(keyset.Key))
|
||||
c.Append("X-Previous-Key", strconv.Itoa(keyset.PreviousKey))
|
||||
c.Append("X-Next-Key", strconv.Itoa(keyset.NextKey))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
15
utils/random.go
Normal file
15
utils/random.go
Normal file
@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
)
|
||||
|
||||
func RandString(nByte int) (string, error) {
|
||||
b := make([]byte, nByte)
|
||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.RawURLEncoding.EncodeToString(b), nil
|
||||
}
|
Reference in New Issue
Block a user