49 Commits

Author SHA1 Message Date
Thomas Peetz 2e80cd9b0e refactor layout
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 9s
2026-10-14 23:08:49 +02:00
Thomas Peetz d5f71efe5e add details view for MediaLoFi
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-13 17:28:44 +02:00
tpeetz b897772ea1 remove nexus.thpeetz.de as proxy
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 11s
2026-10-13 15:22:09 +00:00
tpeetz 2e3e667e6c remove obsolete file
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-12 20:17:20 +02:00
Thomas Peetz 4c603a8eff implement command update-title
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-12 17:37:06 +02:00
tpeetz f5e9cbc423 add config values for token retrieval
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-11 23:04:39 +02:00
tpeetz 58b26304ae update
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 7s
2026-10-11 01:13:58 +02:00
tpeetz 0c5013f4a8 add standalone services
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-10 13:33:46 +00:00
tpeetz bc88c694ee add MediaLofi in kontor-gin (#97)
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
Co-authored-by: Thomas Peetz <thomas.peetz@cimt-ag.de>
Reviewed-on: #97
2026-10-09 16:26:11 +00:00
Thomas Peetz 7116869b42 add lofi by api
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-07 22:39:53 +02:00
Thomas Peetz 094dffb1c7 add loading links form file
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-07 18:50:09 +02:00
Thomas Peetz 980eda29af add tests for repository
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-06 17:11:42 +02:00
tpeetz 32f3f034eb add tests for repository
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-06 00:16:03 +02:00
tpeetz e811fda863 add test for KontorTime
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-04 23:05:53 +02:00
tpeetz dea3c3d36a add parsing multiple time formats
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-04 21:47:00 +02:00
tpeetz 56d2434097 omit empty deleted dates
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-04 21:25:47 +02:00
tpeetz 8c9850d4b1 fix models
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-04 21:15:50 +02:00
tpeetz 570ae71aba add missing model
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-04 21:03:54 +02:00
tpeetz e1b5691fac add models for MailAccount and Mail
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-10-04 20:43:08 +02:00
tpeetz bce0bc2989 add parameters for server and filename
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
2026-10-04 16:13:35 +02:00
tpeetz a5493e6c11 add missing exports
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-04 14:36:04 +02:00
tpeetz b524c3b14a go mod tidy
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-10-04 12:34:38 +02:00
tpeetz d9007ba0e4 add missing models
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-10-04 01:56:25 +02:00
tpeetz ea648082be add command add-link to kontor-cli
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
2026-10-03 01:35:26 +02:00
Thomas Peetz 4aaf580735 WIP: Export Kontor DB
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-10-01 17:40:17 +02:00
Thomas Peetz f5abb44466 WIP: Export Kontor DB
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-30 18:55:59 +02:00
tpeetz 914e1214de remove obsolete files
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-09-30 04:15:45 +02:00
tpeetz f912dcb670 add tysc handlers to kontor-gin 2026-09-30 04:12:33 +02:00
tpeetz c848758821 move schema to models
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-28 09:42:31 +00:00
tpeetz 2d6fa7b7ee add rest client
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-27 03:09:22 +02:00
Thomas Peetz f0f1819a1f umstellung auf Service und Repository Verwendung - WIP
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-25 16:57:23 +02:00
Thomas Peetz 131296c644 change kontor-gin templates
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-09-24 16:06:38 +02:00
Thomas Peetz ba83d70764 add reading configs
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-23 23:19:10 +02:00
Thomas Peetz a0ad4e5c26 change kontor-gin for containers
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-09-23 17:09:48 +02:00
Thomas Peetz 6b5167a5c0 add imags
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-22 22:46:35 +02:00
Thomas Peetz 044da5353a add templates for kontor-gin
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-09-22 19:19:51 +02:00
Thomas Peetz f2f4a0aaf6 add templates for kontor-gin
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
2026-09-21 19:55:46 +02:00
tpeetz 652aa3005b copy layout from kontor-api
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-20 22:17:42 +02:00
tpeetz ad09386a7a update kontor-fiber to use Go Fiber v3
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-20 02:08:56 +02:00
Thomas Peetz 8f5a384e89 add subproject kontor-gin
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-18 17:42:50 +02:00
Thomas Peetz c1d913e36b add Python library diskcache
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-17 16:37:02 +02:00
Thomas Peetz 8a5bc7873a change usage of secret
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-09-16 16:57:42 +02:00
Thomas Peetz 0ad1969614 separate podman pod creation in several files
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 8s
2026-09-15 13:42:09 +02:00
Thomas Peetz d80aefe6b2 add publishing of kontor-model
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
2026-08-26 18:33:35 +02:00
Thomas Peetz 652378e7de update kontor-api
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2026-08-25 17:45:03 +02:00
tpeetz 57b942a9ca update Vaadin to 25.2.6 (#95)
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
Co-authored-by: Thomas Peetz <thomas.peetz@cimt-ag.de>
Reviewed-on: #95
2026-08-25 14:15:18 +00:00
Thomas Peetz bda453a92a change to version 0.4.0-SNAPSHOT
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-08-25 11:11:51 +02:00
Thomas Peetz a113f08ddc create release 0.3.0
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s
2026-08-25 09:43:49 +02:00
tpeetz cc631a14ed Merge pull request 'Vorbereitung Release 03.0' (#94) from develop/0.3.0 into main
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
Reviewed-on: #94
2026-08-25 06:01:17 +00:00
397 changed files with 19985 additions and 1492 deletions
+1
View File
@@ -11,3 +11,4 @@ kontor-robyn.bak
kontor-robyn.bak2 kontor-robyn.bak2
kontor-data/.gradle kontor-data/.gradle
kontor-data/build/ kontor-data/build/
/kontor-api/kontor-api.code-workspace
+1 -1
View File
@@ -4,7 +4,7 @@ NEXUS_URL=https://nexus.thpeetz.de
MAVEN_REPO=maven-snapshots MAVEN_REPO=maven-snapshots
GROUP_ID=de.thpeetz GROUP_ID=de.thpeetz
ARTIFACT_ID=kontor-spring ARTIFACT_ID=kontor-spring
VERSION=0.3.0-SNAPSHOT VERSION=0.4.0
FILE_EXTENSION=jar FILE_EXTENSION=jar
download_url=$(curl -X GET "${NEXUS_URL}/service/rest/v1/search/assets?repository=${MAVEN_REPO}&maven.groupId=${GROUP_ID}&maven.artifactId=${ARTIFACT_ID}&maven.baseVersion=${VERSION}&maven.extension=${FILE_EXTENSION}" -H "accept: application/json" | jq -rc '.items | .[].downloadUrl' | sort | tail -n 1) download_url=$(curl -X GET "${NEXUS_URL}/service/rest/v1/search/assets?repository=${MAVEN_REPO}&maven.groupId=${GROUP_ID}&maven.artifactId=${ARTIFACT_ID}&maven.baseVersion=${VERSION}&maven.extension=${FILE_EXTENSION}" -H "accept: application/json" | jq -rc '.items | .[].downloadUrl' | sort | tail -n 1)
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# script/cibuild:
set -e
cd "$(dirname "$0")/.."
source version
echo " => Baue Image localhost/kontor-angular:$kontorVersion"
buildah build -t kontor-angular:$kontorVersion kontor-angular
-3
View File
@@ -14,9 +14,6 @@ ENV PATH="/root/.local/bin:${PATH}"
WORKDIR /app WORKDIR /app
COPY ./pyproject.toml . COPY ./pyproject.toml .
#RUN --mount=type=bind,source=/home/tpeetz/projects/kontor/kontor-model,target=/container/kontor-model uv add /container/kontor-model
#COPY ../kontor-model/ /container
RUN uv add /container/kontor-model
RUN uv sync RUN uv sync
# ------------------------------- Production Stage ------------------------------ ## # ------------------------------- Production Stage ------------------------------ ##
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# script/cibuild:
set -e
cd "$(dirname "$0")/.."
source version
echo " => Baue Image localhost/kontor-api:$kontorVersion"
buildah build -t kontor-api:$kontorVersion kontor-api
+2 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "kontor-api" name = "kontor-api"
version = "0.1.0" version = "0.4.0"
description = "Add your description here" description = "Add your description here"
readme = "README.md" readme = "README.md"
requires-python = ">=3.13" requires-python = ">=3.13"
@@ -34,3 +34,4 @@ dependencies = [
[tool.uv.sources] [tool.uv.sources]
kontor-model = { path = "../kontor-model", editable = true } kontor-model = { path = "../kontor-model", editable = true }
+51 -2
View File
@@ -1,11 +1,21 @@
from typing import List from typing import List
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, status, HTTPException
from kontor_model.db.models.media import MediaLofi from kontor_model.db.models.media import MediaLofi
from src.db.session import SessionDep from src.db.session import SessionDep
from kontor_model.schema.media.lofi import MediaLofiResponse, lofi_to_response from src.core.log_conf import logger
from kontor_model.schema.media.lofi import (
MediaLofiModel,
MediaLofiResponse,
lofi_to_response,
lofi_to_model
)
from kontor_model.db.repository.media.lofi import (
import_medialofi,
delete_medialofi
)
router = APIRouter() router = APIRouter()
@@ -40,3 +50,42 @@ def get_lofi(lofi_id: str, db: SessionDep) -> MediaLofiResponse:
raise HTTPException(status_code=404, detail="MediaLofi could not be found") raise HTTPException(status_code=404, detail="MediaLofi could not be found")
response = lofi_to_response(lofi) response = lofi_to_response(lofi)
return response return response
@router.delete("/lofi/{lofi_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_lofi(lofi_id: str, db: SessionDep):
"""
Delete MediaFile by given id.
"""
lofi = db.get(MediaLofi, lofi_id)
if not lofi:
raise HTTPException(status_code=404, detail="MediaLofi could not be found")
logger.info("delete MediaLofi: %s", lofi_id)
delete_medialofi(db=db, lofi_id=lofi.id)
@router.put("/lofi/{lofi_id}", response_model=MediaLofiResponse)
def update_lofi(lofi_id: str, db: SessionDep, info: MediaLofiResponse) -> MediaLofiResponse:
"""
Update MediaLofi with given id and data.
"""
media_lofi = db.get(MediaLofi, lofi_id)
if not media_lofi:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="MediaLofi could not be found")
lofi_to_model(info, media_lofi)
db.add(media_lofi)
db.commit()
media_lofi = db.get(MediaLofi, lofi_id)
if not media_lofi:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="MediaLofi could not be found")
response = lofi_to_response(media_lofi)
return response
@router.post("/lofi", status_code=status.HTTP_201_CREATED)
def add_lofi(new_lofi: MediaLofiModel, db: SessionDep) -> MediaLofiResponse:
logger.info("add medialofi %s", new_lofi)
try:
medialofi: MediaLofi = import_medialofi(db, new_lofi)
except:
raise HTTPException(status_code=409, detail="MediaLofi duplicate")
response = lofi_to_response(medialofi)
return response
+9 -5
View File
@@ -9,17 +9,21 @@ load_dotenv(dotenv_path=env_path)
class Settings: class Settings:
PROJECT_NAME: str = "Kontor" PROJECT_NAME: str = "Kontor"
PROJECT_VERSION: str = "0.3.0" PROJECT_VERSION: str = "0.4.0"
DB_USER: str = os.getenv("DB_USER", "kontor") DB_USER: str = os.getenv("DB_USER", "kontor")
DB_PASSWORD: str = os.getenv("DB_PASSWORD", "kontor") DB_PASSWORD: str = os.getenv("DB_PASSWORD", "kontor")
DB_SERVER: str = os.getenv("DB_SERVER", "postgres") DB_SERVER: str = os.getenv("DB_SERVER", "postgres")
DB_PORT: int = int(os.getenv("DB_PORT", 5432)) DB_PORT: int = int(os.getenv("DB_PORT", 5432))
DB_DBNAME: str = os.getenv("DB_DBNAME", "kontor") DB_DBNAME: str = os.getenv("DB_DBNAME", "kontor")
DATABASE_URL: str = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_SERVER}:{DB_PORT}/{DB_DBNAME}" DATABASE_URL: str = (
SECRET_KEY: str = os.getenv("SECRET_KEY", "J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc=") f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_SERVER}:{DB_PORT}/{DB_DBNAME}"
)
SECRET_KEY: str = os.getenv(
"SECRET_KEY", "J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc="
)
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60*24*7 # one week in mins ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # one week in mins
settings = Settings() settings = Settings()
+810 -386
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
# This file was generated by the Gradle 'init' task. # This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties # https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
description='Kontor Documentation' description='Kontor Documentation'
version=0.3.0-SNAPSHOT version=0.4.0-SNAPSHOT
group=de.thpeetz group=de.thpeetz
org.gradle.configuration-cache=true org.gradle.configuration-cache=true
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# script/cibuild:
set -e
cd "$(dirname "$0")/.."
source version
echo " => Baue Image localhost/kontor-echo:$kontorVersion"
buildah build -t kontor-echo:$kontorVersion kontor-echo
+3 -1
View File
@@ -1,5 +1,5 @@
# ---------- Stage 1: Build ---------- # ---------- Stage 1: Build ----------
FROM docker.io/library/golang:1.25-alpine AS builder FROM docker.io/library/golang:1.26-alpine AS builder
# Set the working directory # Set the working directory
WORKDIR /app WORKDIR /app
# Ensure a portable, static-ish binary # Ensure a portable, static-ish binary
@@ -20,5 +20,7 @@ WORKDIR /app
RUN apk add --no-cache ca-certificates tzdata curl RUN apk add --no-cache ca-certificates tzdata curl
# Copy the binary and set ownership # Copy the binary and set ownership
COPY --from=builder /app/kontor /app/kontor COPY --from=builder /app/kontor /app/kontor
COPY --from=builder /app/views /app/views
COPY --from=builder /app/static /app/static
# Set the entrypoint command # Set the entrypoint command
ENTRYPOINT ["/app/kontor"] ENTRYPOINT ["/app/kontor"]
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# script/cibuild:
set -e
cd "$(dirname "$0")/.."
source version
echo " => Baue Image localhost/kontor-fiber:$kontorVersion"
buildah build -t kontor-fiber:$kontorVersion kontor-fiber
+28 -9
View File
@@ -3,11 +3,15 @@ package main
import ( import (
"kontor-api-fiber/pkg/handler" "kontor-api-fiber/pkg/handler"
"kontor-api-fiber/pkg/schema" "kontor-api-fiber/pkg/schema"
"kontor-api-fiber/pkg/web"
"log" "log"
"time"
jwtware "github.com/gofiber/contrib/jwt" jwtware "github.com/gofiber/contrib/v3/jwt"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v3/middleware/logger"
"github.com/gofiber/fiber/v3/middleware/static"
"github.com/gofiber/template/html/v3"
) )
func main() { func main() {
@@ -16,24 +20,39 @@ func main() {
if err := schema.Connect(); err != nil { if err := schema.Connect(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
// Create a new engine
engine := html.New("./views", ".html")
app := fiber.New() app := fiber.New(fiber.Config{
Views: engine,
// app.Use(jwtware.New(jwtware.Config{ ViewsLayout: "layouts/main",
// SigningKey: jwtware.SigningKey{Key: []byte("secret")}, })
// }))
//app.Use(logger.New()) //app.Use(logger.New())
app.Get("/health", handler.GetHealth) app.Get("/health", handler.GetHealth)
app.Post("/login", handler.Login) app.Post("/login", handler.Login)
web.SetupRoutes(app)
api := app.Group("/api", logger.New(), jwtware.New(jwtware.Config{ //api := app.Group("/api/v1")
api := app.Group("/api/v1", logger.New(), jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte("secret")}, SigningKey: jwtware.SigningKey{Key: []byte("secret")},
})) }))
api.Use(logger.New()) api.Use(logger.New())
handler.SetupComicRoutes(api) handler.SetupComicRoutes(api)
handler.SetupMediaRoutes(api) handler.SetupMediaRoutes(api)
app.Get("/*", static.New("./static", static.Config{
Browse: false,
MaxAge: 3600,
CacheDuration: 10 * time.Second,
NotFoundHandler: func(c fiber.Ctx) error {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
"error": "asset not found",
"path": c.Path(),
})
},
}))
// Listen on port 8900 // Listen on port 8900
app.Listen(":8500") app.Listen(":8500")
+45 -28
View File
@@ -1,42 +1,59 @@
module kontor-api-fiber module kontor-api-fiber
go 1.24.2 go 1.26.0
require (
github.com/gofiber/contrib/jwt v1.1.2
github.com/gofiber/fiber/v3 v3.5.0
github.com/gofiber/template/html/v3 v3.0.9
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/stretchr/testify v1.12.1
github.com/uptrace/bun v1.2.18
github.com/uptrace/bun/dialect/pgdialect v1.2.18
github.com/uptrace/bun/driver/pgdriver v1.2.18
github.com/uptrace/bun/extra/bundebug v1.2.18
golang.org/x/crypto v0.57.0
)
require ( require (
github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect github.com/andybalholm/brotli v1.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.19.0 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/go-logr/logr v1.4.4 // indirect
github.com/gofiber/contrib/jwt v1.1.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofiber/fiber/v2 v2.52.10 // indirect github.com/gofiber/contrib/v3/jwt v1.2.4 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/gofiber/fiber/v2 v2.52.15 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/gofiber/schema v1.8.7 // indirect
github.com/gofiber/template/v2 v2.1.2 // indirect
github.com/gofiber/utils/v2 v2.5.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect github.com/klauspost/compress v1.20.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect github.com/mattn/go-colorable v0.1.15 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.24 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.30 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect github.com/molecule-man/go-brrr v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/tinylib/msgp v1.6.4 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/uptrace/bun v1.2.16 // indirect
github.com/uptrace/bun/dialect/pgdialect v1.2.16 // indirect
github.com/uptrace/bun/driver/pgdriver v1.2.16 // indirect
github.com/uptrace/bun/extra/bundebug v1.2.16 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.68.0 // indirect github.com/valyala/fasthttp v1.74.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect go.opentelemetry.io/otel v1.46.0 // indirect
golang.org/x/crypto v0.45.0 // indirect go.opentelemetry.io/otel/metric v1.46.0 // indirect
golang.org/x/sys v0.39.0 // indirect go.opentelemetry.io/otel/trace v1.46.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/mod v0.41.0 // indirect
golang.org/x/net v0.59.0 // indirect
golang.org/x/sync v0.23.0 // indirect
golang.org/x/sys v0.48.0 // indirect
golang.org/x/text v0.42.0 // indirect
golang.org/x/tools v0.49.0 // indirect
mellium.im/sasl v0.3.2 // indirect mellium.im/sasl v0.3.2 // indirect
) )
+102 -56
View File
@@ -1,98 +1,144 @@
github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k= github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k=
github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k= github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/andybalholm/brotli v1.2.4 h1:649LN6qF+/7JJYNN3Wdu4Dt5PS6eC/yP/Go3Bb0/AHI=
github.com/andybalholm/brotli v1.2.4/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
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/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
github.com/fxamacker/cbor/v2 v2.9.3 h1:oQBnFATpNdY8gJHTndDDv5Xl4QqNaz51G5LLEPhng3Q=
github.com/fxamacker/cbor/v2 v2.9.3/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/gofiber/contrib/jwt v1.1.2 h1:GmWnOqT4A15EkA8IPXwSpvNUXZR4u5SMj+geBmyLAjs= github.com/gofiber/contrib/jwt v1.1.2 h1:GmWnOqT4A15EkA8IPXwSpvNUXZR4u5SMj+geBmyLAjs=
github.com/gofiber/contrib/jwt v1.1.2/go.mod h1:CpIwrkUQ3Q6IP8y9n3f0wP9bOnSKx39EDp2fBVgMFVk= github.com/gofiber/contrib/jwt v1.1.2/go.mod h1:CpIwrkUQ3Q6IP8y9n3f0wP9bOnSKx39EDp2fBVgMFVk=
github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o= github.com/gofiber/contrib/v3/jwt v1.2.4 h1:0cApE/65Nb+AV49zMjun2+vXE1pCdZWLdg1z3IxmrPI=
github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM= github.com/gofiber/contrib/v3/jwt v1.2.4/go.mod h1:ARfFxE8uxUeV5hzq9qUaSCBWkpYmGpvAL/XU3NBpkRA=
github.com/gofiber/fiber/v2 v2.52.10 h1:jRHROi2BuNti6NYXmZ6gbNSfT3zj/8c0xy94GOU5elY= github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
github.com/gofiber/fiber/v2 v2.52.10/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo= github.com/gofiber/fiber/v2 v2.52.15 h1:Cov1uKeVPyu9q0jSrN60W+A8XNX+/WK8J7cy5osHLIk=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= github.com/gofiber/fiber/v2 v2.52.15/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= github.com/gofiber/fiber/v3 v3.5.0 h1:dk7TOUH6DXJGtOLsN2XEG+0ZML7cznzHILTVozbNEK8=
github.com/gofiber/fiber/v3 v3.5.0/go.mod h1:GOVDTW+gjJvfe0iJyVujbQ1Lnx+JUjFySJRI/9/xX/w=
github.com/gofiber/schema v1.8.3 h1:06ZedxIYjngzc0095PYy7uWnFnbRflWFpikvZH61fDc=
github.com/gofiber/schema v1.8.3/go.mod h1:jWnnZdhcW1mHyV+VnfRxKJDPNcepJsTZ9RIWxrr32Ng=
github.com/gofiber/schema v1.8.7 h1:7cSagr2ObiUVFuitCOqjKMqIhV+oVbkanP4Ge/wHsnI=
github.com/gofiber/schema v1.8.7/go.mod h1:fBz4T6uOepH3L+dYlz/yzQ0bFHPnfExkp/B3Qrk2VBI=
github.com/gofiber/template/html/v3 v3.0.9 h1:oVgrQIGSe7DcufnD823KwLsUnIgtCDGhznj1kMfNB2I=
github.com/gofiber/template/html/v3 v3.0.9/go.mod h1:Nk2HJlZYaCd0oVEwQd8v+1M+gmweub6dEAeS07WhL6o=
github.com/gofiber/template/v2 v2.1.2 h1:fZTpavK0Yi1ehJGrL9UXzBrOnowZfPpIZwxfiIftXBs=
github.com/gofiber/template/v2 v2.1.2/go.mod h1:h8vOKQkwFUFRNTvRcIvt/OgVUOVqHsaEviWTOAh2JqQ=
github.com/gofiber/utils/v2 v2.5.2 h1:bX+iACKsCGm2+dW7jvkYSiWIsBaKqFy5slFSxJSIL/s=
github.com/gofiber/utils/v2 v2.5.2/go.mod h1:EaVDjy4JJv0m0lg6x4owJ1GG8j1pMO8XriqCgVns1ZQ=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 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/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
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-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/mattn/go-runewidth v0.0.30 h1:+KUuiDA4fF0R1p5FeueHefjDm+GIM+kWfFnDjybOPgk=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/mattn/go-runewidth v0.0.30/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8=
github.com/molecule-man/go-brrr v1.0.1 h1:cEjgx8hgNw6UGdhQ94SPDbPkKuRbkUcxBO3IzbGpA/o=
github.com/molecule-man/go-brrr v1.0.1/go.mod h1:7ybW6/7gA3oKY45jOfVNjSJDtrr6ea4tzbsTkjmQDC4=
github.com/molecule-man/go-brrr v1.1.0 h1:rLBGSXA393y+5ttCBLkW34CHESop5tahrOFxVv/XDEU=
github.com/molecule-man/go-brrr v1.1.0/go.mod h1:7ybW6/7gA3oKY45jOfVNjSJDtrr6ea4tzbsTkjmQDC4=
github.com/molecule-man/go-brrr v1.1.1 h1:KYwusQhjtV3smALnhmafZf4OBrh7vP4p8O47DyUmmuY=
github.com/molecule-man/go-brrr v1.1.1/go.mod h1:7ybW6/7gA3oKY45jOfVNjSJDtrr6ea4tzbsTkjmQDC4=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= 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/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/shamaton/msgpack/v3 v3.2.3 h1:0r0aZtrXDFOPpwWJTEOpFq+Ih/JmMLm0pqLN5mSilrw=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/shamaton/msgpack/v3 v3.2.3/go.mod h1:sgBYvEiyz8JR1NC3yGRoPVME9xXovpnh3l/plW1nfRo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ=
github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= 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/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 h1:QlObi6ZIK5Ao7kAALnh91HWYNZUBbVwye52fmlQM9kc=
github.com/uptrace/bun v1.2.16/go.mod h1:jMoNg2n56ckaawi/O/J92BHaECmrz6IRjuMWqlMaMTM= github.com/uptrace/bun v1.2.16/go.mod h1:jMoNg2n56ckaawi/O/J92BHaECmrz6IRjuMWqlMaMTM=
github.com/uptrace/bun v1.2.18 h1:3HnRcMfS6OBPMG1eSOzlbFJ/X/AyMEJb7rMxE6VQvDU=
github.com/uptrace/bun v1.2.18/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 h1:KFNZ0LxAyczKNfK/IJWMyaleO6eI9/Z5tUv3DE1NVL4=
github.com/uptrace/bun/dialect/pgdialect v1.2.16/go.mod h1:IJdMeV4sLfh0LDUZl7TIxLI0LipF1vwTK3hBC7p5qLo= github.com/uptrace/bun/dialect/pgdialect v1.2.16/go.mod h1:IJdMeV4sLfh0LDUZl7TIxLI0LipF1vwTK3hBC7p5qLo=
github.com/uptrace/bun/dialect/pgdialect v1.2.18 h1:IZ6nM2+OYrL8lkEAy7UkSEZvoa3vluTAUlZfPtlRB2k=
github.com/uptrace/bun/dialect/pgdialect v1.2.18/go.mod h1:Tqdf4QP1okrGYpXfodXvCOK6Ob1OOTwSaoAzCgBB3IU=
github.com/uptrace/bun/driver/pgdriver v1.2.16 h1:b1kpXKUxtTSGYow5Vlsb+dKV3z0R7aSAJNfMfKp61ZU= 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/pgdriver v1.2.16/go.mod h1:H6lUZ9CBfp1X5Vq62YGSV7q96/v94ja9AYFjKvdoTk0=
github.com/uptrace/bun/driver/pgdriver v1.2.18 h1:Zojuc83ulApocXomBLEcx1DqCZweREafHCjPfyXo88I=
github.com/uptrace/bun/driver/pgdriver v1.2.18/go.mod h1:ZRJcARw93nxbQ5WawTrc5EO+F+GygkcYgDLEnT17CcE=
github.com/uptrace/bun/extra/bundebug v1.2.16 h1:3OXAfHTU4ydu2+4j05oB1BxPx6+ypdWIVzTugl/7zl0= github.com/uptrace/bun/extra/bundebug v1.2.16 h1:3OXAfHTU4ydu2+4j05oB1BxPx6+ypdWIVzTugl/7zl0=
github.com/uptrace/bun/extra/bundebug v1.2.16/go.mod h1:vk6R/1i67/S2RvUI5AH/m3P5e67mOkfDCmmCsAPUumo= github.com/uptrace/bun/extra/bundebug v1.2.16/go.mod h1:vk6R/1i67/S2RvUI5AH/m3P5e67mOkfDCmmCsAPUumo=
github.com/uptrace/bun/extra/bundebug v1.2.18 h1:5cgkqdvhpSHIEONazSytm4RWYFneNtcznaWLt6r8m4M=
github.com/uptrace/bun/extra/bundebug v1.2.18/go.mod h1:M+U9YJVJcmk0RrszCb2Q1oskJiJ0LuC44FxDhZLP1ws=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 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/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= github.com/valyala/fasthttp v1.73.0 h1:ocTOORnBWtJ+P8t/6wAjdkchMzdfHmWx2VD/DPbgZ7s=
github.com/valyala/fasthttp v1.68.0 h1:v12Nx16iepr8r9ySOwqI+5RBJ/DqTxhOy1HrHoDFnok= github.com/valyala/fasthttp v1.73.0/go.mod h1:EtXQDHaR+5P18p8wqDRFpUhxr108Ga9mXvVJXHRrN2k=
github.com/valyala/fasthttp v1.68.0/go.mod h1:5EXiRfYQAoiO/khu4oU9VISC/eVY6JqmSpPJoHCKsz4= github.com/valyala/fasthttp v1.74.0 h1:wMS9fnO2QTALozYx5pId2Vi7ZwU/epUkY8i/KPWCHoU=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/valyala/fasthttp v1.74.0/go.mod h1:3ARmLamUcw7ElxVtC8PXaGzQ6VEuvnetlkrwIklQBSE=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0= mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0=
mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY= mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY=
+3 -3
View File
@@ -5,12 +5,12 @@ import (
"kontor-api-fiber/pkg/schema" "kontor-api-fiber/pkg/schema"
"kontor-api-fiber/pkg/utils" "kontor-api-fiber/pkg/utils"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v3"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
"github.com/uptrace/bun" "github.com/uptrace/bun"
) )
func Login(c *fiber.Ctx) error { func Login(c fiber.Ctx) error {
user := c.FormValue("user") user := c.FormValue("user")
pass := c.FormValue("pass") pass := c.FormValue("pass")
@@ -39,7 +39,7 @@ func Login(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"token": token}) return c.JSON(fiber.Map{"token": token})
} }
func Restricted(c *fiber.Ctx) error { func Restricted(c fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token) user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims) claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string) name := claims["name"].(string)
+4 -4
View File
@@ -5,7 +5,7 @@ import (
"kontor-api-fiber/pkg/schema" "kontor-api-fiber/pkg/schema"
"log" "log"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v3"
"github.com/uptrace/bun" "github.com/uptrace/bun"
) )
@@ -16,7 +16,7 @@ func SetupComicRoutes(api fiber.Router) {
comics.Get("/comicworks", GetAllComicWorks) comics.Get("/comicworks", GetAllComicWorks)
} }
func GetAllComics(c *fiber.Ctx) error { func GetAllComics(c fiber.Ctx) error {
var comics []schema.Comic var comics []schema.Comic
var err error var err error
var db *bun.DB var db *bun.DB
@@ -36,7 +36,7 @@ func GetAllComics(c *fiber.Ctx) error {
return c.JSON(comics) return c.JSON(comics)
} }
func GetAllPublishers(c *fiber.Ctx) error { func GetAllPublishers(c fiber.Ctx) error {
var publishers []schema.Publisher var publishers []schema.Publisher
var err error var err error
var db *bun.DB var db *bun.DB
@@ -56,7 +56,7 @@ func GetAllPublishers(c *fiber.Ctx) error {
return c.JSON(publishers) return c.JSON(publishers)
} }
func GetAllComicWorks(c *fiber.Ctx) error { func GetAllComicWorks(c fiber.Ctx) error {
var comic_works []schema.ComicWork var comic_works []schema.ComicWork
var err error var err error
var db *bun.DB var db *bun.DB
+2 -2
View File
@@ -1,8 +1,8 @@
package handler package handler
import "github.com/gofiber/fiber/v2" import "github.com/gofiber/fiber/v3"
func GetHealth(c *fiber.Ctx) error { func GetHealth(c fiber.Ctx) error {
return c.Status(200).JSON(&fiber.Map{ return c.Status(200).JSON(&fiber.Map{
"status": "ok", "status": "ok",
}) })
+3 -3
View File
@@ -8,7 +8,7 @@ import (
"log" "log"
"time" "time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v3"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/uptrace/bun" "github.com/uptrace/bun"
) )
@@ -19,7 +19,7 @@ func SetupMediaRoutes(api fiber.Router) {
media.Post("/files", AddFile) media.Post("/files", AddFile)
} }
func GetAllFiles(c *fiber.Ctx) error { func GetAllFiles(c fiber.Ctx) error {
var files []schema.MediaFile var files []schema.MediaFile
var err error var err error
var db *bun.DB var db *bun.DB
@@ -38,7 +38,7 @@ func GetAllFiles(c *fiber.Ctx) error {
return c.JSON(files) return c.JSON(files)
} }
func AddFile(c *fiber.Ctx) error { func AddFile(c fiber.Ctx) error {
var err error var err error
var db *bun.DB var db *bun.DB
ctx := context.Background() ctx := context.Background()
+14
View File
@@ -24,6 +24,20 @@ type MediaFile struct {
MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_file_id"` MediaActorFiles []MediaActorFile `bun:"rel:has-many,join:id=media_file_id"`
} }
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"`
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"`
}
type MediaActor struct { type MediaActor struct {
bun.BaseModel `bun:"table:media_actor"` bun.BaseModel `bun:"table:media_actor"`
+9
View File
@@ -0,0 +1,9 @@
package web
import "github.com/gofiber/fiber/v3"
func Mainpage(c fiber.Ctx) error {
return c.Render("index", fiber.Map{
"Title": "Kontor Fiber",
})
}
+12
View File
@@ -0,0 +1,12 @@
package web
import (
"github.com/gofiber/fiber/v3"
)
func SetupRoutes(app *fiber.App) {
app.Get("/", Mainpage)
app.Get("/comic/comics", Mainpage)
app.Get("/media/files", Mainpage)
}
+172
View File
@@ -0,0 +1,172 @@
* {
box-sizing: border-box;
}
body {
font-family: Arial;
padding: 10px;
background: lightgrey;
}
/* Header/Blog Title */
.header {
padding: 30px;
text-align: center;
background-color: lightblue;
}
.header h1 {
font-size: 50px;
}
/* Style the top navigation bar */
.topnav {
overflow: hidden;
background-color: darkgrey;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
.subnav {
overflow: hidden;
background-color: grey;
}
.subnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.form-inline {
display: flex;
flex-flow: row wrap;
align-items: center;
padding-top: 10px;
padding-left: 20px;
}
.form-inline label {
margin: 5px 10px 5px 0;
}
.form-inline input {
padding-right: 50px;
margin-right: 10px;
}
.form-inline button {
padding: 10px 20px;
background-color: dodgerblue;
border: 1px solid #ddd;
color: white;
border-radius: 10px;
}
.form-inline button:hover {
background-color: royalblue;
}
.pill-nav a {
display: inline-block;
color: white;
background-color: dodgerblue;
text-align: center;
padding: 10px;
text-decoration: none;
border-radius: 10px;
margin-left: 20px;
}
/* Change the color of links on mouse-over */
.pill-nav a:hover {
background-color: royalblue;
color: white;
}
/* Add a color to the active/current link */
.pill-nav a.active {
background-color: royalblue;
color: white;
}
.maincolumn {
float:left;
width: 100%;
}
/* Create two unequal columns that floats next to each other */
/* Left column */
.leftcolumn {
float: left;
width: 75%;
}
/* Right column */
.rightcolumn {
float: left;
width: 25%;
background-color: #f1f1f1;
padding-left: 20px;
}
/* Fake image */
.fakeimg {
background-color: #aaa;
width: 100%;
padding: 20px;
}
/* Add a card effect for articles */
.card {
background-color: white;
padding: 20px;
margin-top: 20px;
}
/* Clear floats after the columns */
.row::after {
content: "";
display: table;
clear: both;
}
/* Footer */
.footer {
padding: 20px;
text-align: center;
background: #ddd;
margin-top: 20px;
}
/* Responsive layout - when the screen is less than 800px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 800px) {
.leftcolumn, .rightcolumn {
width: 100%;
padding: 0;
}
}
/* Responsive layout - when the screen is less than 400px wide, make the navigation links stack on top of each other instead of next to each other */
@media screen and (max-width: 400px) {
.topnav a {
float: none;
width: 100%;
}
}
+1
View File
@@ -0,0 +1 @@
<h1>{{.Title}}</h1>
+22
View File
@@ -0,0 +1,22 @@
<!doctype html>
<html lang="de-DE">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="/style/main.css" />
<title>{{.Title}}</title>
</head>
<body>
<div class="header">{{template "partials/header" .}}</div>
{{template "partials/navbar" .}}
<div class="content">{{embed}}</div>
<div class="footer">{{template "partials/footer" .}}</div>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<h2>Footer</h2>
+1
View File
@@ -0,0 +1 @@
<h2>Header</h2>
@@ -0,0 +1,6 @@
<div class="subnav">
<a href="/media/files/">MediaFiles</a>
<a href="/media/actors/">MediaActors</a>
<a href="/media/videos/">MediaVideos</a>
<a href="/media/lofi/">MediaLofi</a>
</div>
+7
View File
@@ -0,0 +1,7 @@
<div class="topnav">
<a href="/">Kontor</a>
<a href="/comic/comics">Comics</a>
<a href="/media/files">Media</a>
<a style="float:right" href="/login/">Login</a></li>
</div>
+28
View File
@@ -0,0 +1,28 @@
# ---------- Stage 1: Build ----------
FROM docker.io/library/golang:1.26-alpine AS builder
# Set the working directory
WORKDIR /app
# Ensure a portable, static-ish binary
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
# Copy and download dependencies
COPY go.mod go.sum ./
RUN go mod download
# Copy the source code
COPY . .
# Build the Go application (strip debug info for smaller size)
RUN go build -trimpath -ldflags="-s -w" -o kontor cmd/kontor/main.go
# ---------- Stage 2: Final ----------
FROM alpine:latest
# Set the working directory
WORKDIR /app
# Install runtime dependencies you actually need
RUN apk add --no-cache ca-certificates tzdata curl
# Copy the binary and set ownership
COPY --from=builder /app/kontor /app/kontor
#COPY --from=builder /app/kontor-gin /app/kontor-gin
#COPY --from=builder /app/templates /app/templates
#COPY --from=builder /app/assets /app/assets
#ENV GIN_MODE=release
# Set the entrypoint command
ENTRYPOINT ["/app/kontor"]
+11
View File
@@ -0,0 +1,11 @@
FROM docker.io/library/golang:1.26-alpine
# Install runtime dependencies you actually need
RUN apk add --no-cache ca-certificates tzdata curl git make musl-dev go
# Set the working directory
WORKDIR /app
# Copy the binary and set ownership
COPY ./kontor kontor
EXPOSE 8550
ENV DB_HOST=postgres DB_USER=kontor DB_PASSWORD=kontor DB_NAME=kontor DB_PORT=5432
# Set the entrypoint command
ENTRYPOINT ["/app/kontor"]
+8
View File
@@ -0,0 +1,8 @@
package assets
import (
"embed"
)
//go:embed style/* icons/*
var StaticFiles embed.FS
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

+172
View File
@@ -0,0 +1,172 @@
* {
box-sizing: border-box;
}
body {
font-family: Arial;
padding: 10px;
background: lightgrey;
}
/* Header/Blog Title */
.header {
padding: 30px;
text-align: center;
background-color: lightblue;
}
.header h1 {
font-size: 50px;
}
/* Style the top navigation bar */
.topnav {
overflow: hidden;
background-color: darkgrey;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
.subnav {
overflow: hidden;
background-color: grey;
}
.subnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.form-inline {
display: flex;
flex-flow: row wrap;
align-items: center;
padding-top: 10px;
padding-left: 20px;
}
.form-inline label {
margin: 5px 10px 5px 0;
}
.form-inline input {
padding-right: 50px;
margin-right: 10px;
}
.form-inline button {
padding: 10px 20px;
background-color: dodgerblue;
border: 1px solid #ddd;
color: white;
border-radius: 10px;
}
.form-inline button:hover {
background-color: royalblue;
}
.pill-nav a {
display: inline-block;
color: white;
background-color: dodgerblue;
text-align: center;
padding: 10px;
text-decoration: none;
border-radius: 10px;
margin-left: 20px;
}
/* Change the color of links on mouse-over */
.pill-nav a:hover {
background-color: royalblue;
color: white;
}
/* Add a color to the active/current link */
.pill-nav a.active {
background-color: royalblue;
color: white;
}
.maincolumn {
float:left;
width: 100%;
}
/* Create two unequal columns that floats next to each other */
/* Left column */
.leftcolumn {
float: left;
width: 75%;
}
/* Right column */
.rightcolumn {
float: left;
width: 25%;
background-color: #f1f1f1;
padding-left: 20px;
}
/* Fake image */
.fakeimg {
background-color: #aaa;
width: 100%;
padding: 20px;
}
/* Add a card effect for articles */
.card {
background-color: white;
padding: 20px;
margin-top: 20px;
}
/* Clear floats after the columns */
.row::after {
content: "";
display: table;
clear: both;
}
/* Footer */
.footer {
padding: 20px;
text-align: center;
background: #ddd;
margin-top: 20px;
}
/* Responsive layout - when the screen is less than 800px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 800px) {
.leftcolumn, .rightcolumn {
width: 100%;
padding: 0;
}
}
/* Responsive layout - when the screen is less than 400px wide, make the navigation links stack on top of each other instead of next to each other */
@media screen and (max-width: 400px) {
.topnav a {
float: none;
width: 100%;
}
}
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# script/cibuild:
set -e
cd "$(dirname "$0")/.."
source version
echo " => Baue Image localhost/kontor-gin:$kontorVersion"
buildah build -t kontor-gin:$kontorVersion kontor-gin
+9
View File
@@ -0,0 +1,9 @@
package main
import (
"kontor-api-gin/internal/cmd"
)
func main() {
cmd.Execute()
}
+85
View File
@@ -0,0 +1,85 @@
package main
import (
"context"
"fmt"
"kontor-api-gin/internal/config"
"kontor-api-gin/internal/handlers"
"kontor-api-gin/internal/router"
"log"
"log/slog"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
)
func main() {
slog.Info("Kontor started")
if err := config.InitConfig(); err != nil {
log.Fatalf("Failed to initialize config: %v", err)
}
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%d sslmode=disable",
viper.GetString("db.host"),
viper.GetString("db.user"),
viper.GetString("db.password"),
viper.GetString("db.name"),
viper.GetInt("db.port"),
)
db, err := config.NewDB(dsn)
if err != nil {
log.Fatal(err)
}
if err := db.AutoMigrate(); err != nil {
log.Fatal(err)
}
// Set Gin mode based on environment
// Production mode disables debug output
if viper.GetString("gin.mode") == "release" {
gin.SetMode(gin.ReleaseMode)
}
r := router.New(
handlers.NewAdminHandler(db, []byte(viper.GetString("api_secret"))),
handlers.NewBookshelfHandler(db),
handlers.NewComicsHandler(db),
handlers.NewMediaHandler(db),
handlers.NewTyscHandler(db),
handlers.NewWebAppHandler(db, []byte(viper.GetString("api_secret"))),
)
srv := &http.Server{
Addr: ":" + strconv.Itoa(viper.GetInt("port")),
Handler: r,
ReadHeaderTimeout: 5 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}()
slog.Info("server up", "address", srv.Addr)
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
_ = srv.Shutdown(ctx)
slog.Info("server stopped")
slog.Info("Kontor finished")
}
+75
View File
@@ -0,0 +1,75 @@
module kontor-api-gin
go 1.26.8
require (
github.com/JanikL/go-artemis v0.0.0-20250315150102-10f50406b94d
github.com/gin-contrib/cors v1.7.2
github.com/gin-contrib/sessions v1.1.2
github.com/gin-contrib/slog v1.1.0
github.com/gin-gonic/gin v1.12.0
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/spf13/cobra v1.10.2
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.12.1
golang.org/x/crypto v0.57.0
golang.org/x/time v0.16.0
gorm.io/driver/postgres v1.6.3
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.2
resty.dev/v3 v3.0.0-rc.4
)
require (
github.com/bytedance/gopkg v0.1.4 // indirect
github.com/bytedance/sonic v1.15.4 // indirect
github.com/bytedance/sonic/loader v0.5.2 // indirect
github.com/cloudwego/base64x v0.1.7 // indirect
github.com/fsnotify/fsnotify v1.10.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.15 // indirect
github.com/gin-contrib/sse v1.1.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.30.3 // indirect
github.com/go-stomp/stomp v2.1.4+incompatible // indirect
github.com/go-stomp/stomp/v3 v3.1.5 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/goccy/go-json v0.10.6 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.4.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.11.0 // indirect
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/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
github.com/leodido/go-urn v1.5.0 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.60.0 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.2 // indirect
go.mongodb.org/mongo-driver/v2 v2.8.0 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/arch v0.31.0 // indirect
golang.org/x/net v0.59.0 // indirect
golang.org/x/sync v0.23.0 // indirect
golang.org/x/sys v0.48.0 // indirect
golang.org/x/text v0.42.0 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)
+203
View File
@@ -0,0 +1,203 @@
github.com/JanikL/go-artemis v0.0.0-20250315150102-10f50406b94d h1:kXaXwcE0eB92pqrluNv1/9IlSJyn56g8Kfl9KdFbHUM=
github.com/JanikL/go-artemis v0.0.0-20250315150102-10f50406b94d/go.mod h1:vVJ6kbfbD0LWMirPFhis2ZZCg5kP6IZYAbRJEGBJwE0=
github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=
github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
github.com/bytedance/sonic v1.15.4 h1:FgtV/4aBHpla9AxuMpuuzVUpa/Cf3izufkxNmnEzdI8=
github.com/bytedance/sonic v1.15.4/go.mod h1:8e51yTPdY8M6t+vvGL1c2Y1xL9i+frEeIAQAEl75NUc=
github.com/bytedance/sonic/loader v0.5.2 h1:0QtP1gevc1OZ6/H8Lb9BRZiCXd1Ftjd3OKuj1T1lBIo=
github.com/bytedance/sonic/loader v0.5.2/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI=
github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
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/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI=
github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ=
github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
github.com/gin-contrib/sessions v1.1.2 h1:utWRqOHT/kbqxxqF/mtutV9wfGLi1+uu5YuvWUhj/Ow=
github.com/gin-contrib/sessions v1.1.2/go.mod h1:qRxYwA/TYJw0wv28oFzs4gY/8G8z69id862SNgX9Gmw=
github.com/gin-contrib/slog v1.1.0 h1:K9MVNrETT6r/C3u2Aheer/gxwVeVqrGL0hXlsmv3fm4=
github.com/gin-contrib/slog v1.1.0/go.mod h1:PvNXQVXcVOAaaiJR84LV1/xlQHIaXi9ygEXyBkmjdkY=
github.com/gin-contrib/sse v1.1.2 h1:MU2fgl1RrdYTMcgJLtz2kJF+vPg3xrqaaKfUUU18tCo=
github.com/gin-contrib/sse v1.1.2/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s=
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8=
github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc=
github.com/go-stomp/stomp v2.1.4+incompatible h1:D3SheUVDOz9RsjVWkoh/1iCOwD0qWjyeTZMUZ0EXg2Y=
github.com/go-stomp/stomp v2.1.4+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c=
github.com/go-stomp/stomp/v3 v3.1.5 h1:Pikz1OSusmSKUm5mRKYfXQZaDatfZ+EnBBA1JJ2xENQ=
github.com/go-stomp/stomp/v3 v3.1.5/go.mod h1:ztzZej6T2W4Y6FlD+Tb5n7HQP3/O5UNQiuC169pIp10=
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/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
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/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg=
github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
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/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0=
github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE=
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0=
github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.60.0 h1:xcQioE8OM66UQLeUMHltK1CCcOu3JbVB4JAQdDQSB+0=
github.com/quic-go/quic-go v0.60.0/go.mod h1:wpKpjmPpftl30sL6pFh7REVpjbcCVy4zt2vDyK1TuJk=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
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/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.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
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=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc=
github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.mongodb.org/mongo-driver/v2 v2.8.0 h1:CxWDGQYY8QQwNjAl/aq2sfWakdnWZynnqJ9F4DhHbP8=
go.mongodb.org/mongo-driver/v2 v2.8.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/arch v0.31.0 h1:22MlEb14/O/EPCYHFxsDdv5TuLD5dMjT5e2QeJw4ULk=
golang.org/x/arch v0.31.0/go.mod h1:KcJSod3cqT2dKcjBxqTyGfbumNikqU9p5tHJinPJnuY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues=
golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.6.3 h1:bAn6O2pUa8LtpWEvL5NFU4+52Tfx8Ut7IVaIacCLcI0=
gorm.io/driver/postgres v1.6.3/go.mod h1:0c4fQA44XhOklXDkgtuKqysHCycTa5i9e3EIpDGCwXk=
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo=
gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
resty.dev/v3 v3.0.0-rc.4 h1:n3360yEcFiyrX5Vkc9XG3Y8kMM24alRBxJ9Ev1mLmqs=
resty.dev/v3 v3.0.0-rc.4/go.mod h1:NTOerrC/4T7/FE6tXIZGIysXXBdgNqwMZuKtxpea9NM=
+309
View File
@@ -0,0 +1,309 @@
package api
import (
"encoding/json"
"fmt"
"kontor-api-gin/internal/config"
"kontor-api-gin/internal/models"
"log/slog"
"os"
"resty.dev/v3"
)
type Login struct {
Email string
Password string
}
type LoginResponse struct {
Token string
}
type ExportData struct {
Sport models.SportDTOList `json:"sport"`
Player models.PlayerDTOList `json:"player"`
Team []models.TeamDTO `json:"team"`
Position []models.PositionDTO `json:"field_position"`
Rooster []models.RoosterDTO `json:"rooster"`
Vendor []models.VendorDTO `json:"vendor"`
CardSet []models.CardSetDTO `json:"card_set"`
Card []models.CardDTO `json:"card"`
Artist []models.ArtistDTO `json:"artist"`
Publisher []models.PublisherDTO `json:"publisher"`
Worktype []models.WorkTypeDTO `json:"worktype"`
Comic []models.ComicDTO `json:"comic"`
Volume []models.VolumeDTO `json:"volume"`
StoryArc []models.StoryArcDTO `json:"story_arc"`
Issue []models.IssueDTO `json:"issue"`
TradePaperback []models.TradePaperbackDTO `json:"trade_paperback"`
ComicWork []models.ComicworkDTO `json:"comic_work"`
IssueWork []models.IssueworkDTO `json:"issue_work"`
Article []models.ArticleDTO `json:"article"`
BookshelfPublisher []models.BookshelfPublisherDTO `json:"bookshelf_publisher"`
Book []models.BookDTO `json:"book"`
Author []models.AuthorDTO `json:"author"`
ArticleAuthor []models.ArticleAuthorDTO `json:"article_author"`
BookAuthor []models.BookAuthorDTO `json:"book_author"`
MediaArticle []models.MediaArticleDTO `json:"media_article"`
MediaVideo []models.MediaVideoDTO `json:"media_video"`
MediaLoFi models.MediaLoFiDTOList `json:"media_lofi"`
MediaFile []models.MediaFileDTO `json:"media_file"`
MediaActor []models.MediaActorDTO `json:"media_actor"`
MediaActorFile []models.MediaActorFileDTO `json:"media_actor_file"`
Profile []models.ProfileDTO `json:"profile"`
Permission []models.PermissionDTO `json:"permission"`
Assignment []models.AssignmentDTO `json:"assignment"`
Token []models.TokenDTO `json:"token"`
MailAccount []models.MailAccountDTO `json:"mail_account"`
Mail []models.MailDTO `json:"mail"`
}
func (e *ExportData) GetMap() map[string]any {
dataMap := make(map[string]any)
for path, value := range Registry {
switch path {
case "tysc/sports":
dataMap["sports"] = value
case "tysc/players":
dataMap["players"] = value
}
}
return dataMap
}
var (
Sports models.SportDTOList
Players models.PlayerDTOList
Teams []models.TeamDTO
Positions []models.PositionDTO
Roosters []models.RoosterDTO
Vendors []models.VendorDTO
Cardsets []models.CardSetDTO
Cards []models.CardDTO
Artists []models.ArtistDTO
Publishers []models.PublisherDTO
Worktypes []models.WorkTypeDTO
Comics []models.ComicDTO
Volumes []models.VolumeDTO
Storyarcs []models.StoryArcDTO
Issues []models.IssueDTO
Tradepaperbacks []models.TradePaperbackDTO
Comicworks []models.ComicworkDTO
Issueworks []models.IssueworkDTO
Articles []models.ArticleDTO
Bookshelf_publishers []models.BookshelfPublisherDTO
Books []models.BookDTO
Authors []models.AuthorDTO
Article_authors []models.ArticleAuthorDTO
Book_authors []models.BookAuthorDTO
Mediaarticles []models.MediaArticleDTO
Mediavideos []models.MediaVideoDTO
Mediaactors []models.MediaActorDTO
Mediaactorfiles []models.MediaActorFileDTO
Mediafiles []models.MediaFileDTO
Medialofis models.MediaLoFiDTOList
Profiles []models.ProfileDTO
Permissions []models.PermissionDTO
Assignments []models.AssignmentDTO
Tokens []models.TokenDTO
Mailaccounts []models.MailAccountDTO
Mail []models.MailDTO
)
var Registry map[string]any
func GetToken(client *resty.Client, server config.Server) (token string) {
var login LoginResponse
body := Login{
Email: server.Username,
Password: server.Password,
}
PostJSON(client, server, "", "api", "login", body, &login)
// _, err := client.R().
// SetBody(body).
// SetHeader("Accept", "application/json").
// SetResult(&login).
// Post(fmt.Sprintf("%s/api/login", server.Url))
// if err != nil {
// slog.Info("Health", "error", err.Error())
// }
if config.Verbose > 2 {
slog.Info("login", "token", login.Token)
}
return login.Token
}
func GetData(server config.Server, apiVersion string) (data *ExportData, err error) {
client := resty.New()
client.SetLoggerWarnLevel(true)
token := GetToken(client, server)
for path, value := range Registry {
GetJSON(client, token, server, path, value)
}
export := ExportData{
Sport: Sports,
Player: Players,
Team: Teams,
Position: Positions,
Rooster: Roosters,
Vendor: Vendors,
CardSet: Cardsets,
Card: Cards,
Artist: Artists,
Publisher: Publishers,
Worktype: Worktypes,
Comic: Comics,
Volume: Volumes,
StoryArc: Storyarcs,
Issue: Issues,
TradePaperback: Tradepaperbacks,
ComicWork: Comicworks,
IssueWork: Issueworks,
Article: Articles,
BookshelfPublisher: Bookshelf_publishers,
Book: Books,
Author: Authors,
ArticleAuthor: Article_authors,
BookAuthor: Book_authors,
MediaArticle: Mediaarticles,
MediaVideo: Mediavideos,
MediaActor: Mediaactors,
MediaActorFile: Mediaactorfiles,
MediaFile: Mediafiles,
MediaLoFi: Medialofis,
Profile: Profiles,
Permission: Permissions,
Assignment: Assignments,
Token: Tokens,
MailAccount: Mailaccounts,
Mail: Mail,
}
defer client.Close()
return &export, nil
}
func DeleteData(target config.Server, path, id string) {
url := fmt.Sprintf("%s/%s/%s/%s", target.Url, config.Config.ApiVersion, path, id)
client := resty.New()
client.SetLoggerWarnLevel(true)
token := GetToken(client, target)
_, err := client.R().
SetAuthToken(token).
SetHeader("Accept", "application/json").
Delete(url)
if err != nil {
slog.Info(url, "error", err.Error())
}
}
func UpdateData(target config.Server, path string, v any) {
client := resty.New()
client.SetLoggerWarnLevel(true)
token := GetToken(client, target)
var result any
PostJSON(client, target, token, config.Config.ApiVersion, path, v, &result)
}
func WriteJson(data *ExportData, fileName string) error {
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
slog.Info("JSON MarshalIndent failed", "Error:", err)
return err
}
// Write bytes to file
err = os.WriteFile(fileName, jsonData, 0644)
if err != nil {
slog.Info("Error writing file:", "Error", err)
return err
}
return nil
}
func GetJSON(client *resty.Client, token string, server config.Server, path string, v any) {
url := fmt.Sprintf("%s/%s/%s", server.Url, config.Config.ApiVersion, path)
if config.Verbose > 2 {
slog.Info("GetJSON", "url", url)
}
var err error
if token == "" {
_, err = client.R().
SetHeader("Accept", "application/json").
SetResult(v).
Get(url)
} else {
_, err = client.R().
SetAuthToken(token).
SetHeader("Accept", "application/json").
SetResult(v).
Get(url)
}
if err != nil {
slog.Info(url, "error", err.Error())
}
if config.Verbose > 2 {
slog.Info("GetJSON", "value", v)
}
}
func PostJSON(client *resty.Client, server config.Server, token string, apiVersion string, path string, body any, v any) {
url := fmt.Sprintf("%s/%s/%s", server.Url, apiVersion, path)
if config.Verbose > 2 {
slog.Info("PostJSON", "url", url)
}
response, err := client.R().
SetAuthToken(token).
SetBody(body).
SetHeader("Accept", "application/json").
SetResult(v).
Post(url)
if err != nil {
slog.Info("PostJSON", "error", err.Error())
}
if config.Verbose > 2 {
slog.Info("PostJSON", "response", response)
}
}
func init() {
Registry = map[string]any{
"tysc/sports": &Sports,
"tysc/players": &Players,
"tysc/teams": &Teams,
"tysc/positions": &Positions,
"tysc/roosters": &Roosters,
"tysc/vendors": &Vendors,
"tysc/cardsets": &Cardsets,
"tysc/cards": &Cards,
"comics/artists": &Artists,
"comics/publishers": &Publishers,
"comics/worktypes": &Worktypes,
"comics/comics": &Comics,
"comics/volumes": &Volumes,
"comics/storyarcs": &Storyarcs,
"comics/issues": &Issues,
"comics/tradepaperbacks": &Tradepaperbacks,
"comics/comicworks": &Comicworks,
"comics/issueworks": &Issueworks,
"bookshelf/articles": &Articles,
"bookshelf/publishers": &Bookshelf_publishers,
"bookshelf/books": &Books,
"bookshelf/authors": &Authors,
"bookshelf/articleauthors": &Article_authors,
"bookshelf/bookauthors": &Book_authors,
"media/articles": &Mediaarticles,
"media/videos": &Mediavideos,
"media/actors": &Mediaactors,
"media/files": &Mediafiles,
"media/actorfiles": &Mediaactorfiles,
"media/lofis": &Medialofis,
"user/profiles": &Profiles,
"user/permissions": &Permissions,
"user/assignments": &Assignments,
"user/tokens": &Tokens,
"admin/mailaccounts": &Mailaccounts,
"user/mail": &Mail,
}
}
+48
View File
@@ -0,0 +1,48 @@
package cmd
import (
"encoding/json"
"log"
"log/slog"
"github.com/go-stomp/stomp/v3"
"github.com/spf13/cobra"
)
type Link struct {
Url string `json:"url"`
}
var addLinkCmd = &cobra.Command{
Use: "add-link",
Short: "Add Link",
Long: "Add Link to Kontor Database",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("add-link kontor started")
conn, err := stomp.Dial("tcp", "localhost:61616",
stomp.ConnOpt.Login("artemis", "artemis"), // Provide username and password
)
if err != nil {
log.Fatalf("failed to connect to Artemis: %s", err)
}
defer conn.Disconnect()
// sender := artemis.Sender{Addr: "localhost:61616", Dest: "add-link", Enc: artemis.EncodingJson}
link := &Link{Url: args[0]}
b, jsonErr := json.Marshal(link)
if jsonErr != nil {
slog.Info("Json encoding failed", "error", jsonErr.Error())
}
err = conn.Send("/queue/add-link", "application/json", b)
if err != nil {
slog.Info("send failed", "error", err.Error())
}
slog.Info("add-link kontor finished")
},
}
func init() {
rootCmd.AddCommand(addLinkCmd)
}
+59
View File
@@ -0,0 +1,59 @@
package cmd
import (
"fmt"
"kontor-api-gin/internal/api"
"kontor-api-gin/internal/config"
"kontor-api-gin/internal/helpers"
"kontor-api-gin/internal/models"
"log/slog"
"os"
"github.com/spf13/cobra"
"resty.dev/v3"
)
var (
servername string
)
var addLinksCmd = &cobra.Command{
Use: "add-links [file]",
Short: "Add Links",
Long: "Add Links",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
fileName := args[0]
slog.Info(fmt.Sprintf("add Links from %s", fileName))
lines, err := helpers.LinesInFile(fileName)
if err != nil {
slog.Warn("add links failed", "error", err)
os.Exit(1)
}
client := resty.New()
localServer := config.Config.Server[servername]
token := api.GetToken(client, localServer)
for _, line := range lines {
lofiAdd := models.MediaLofiAdd{Url: line}
addResult := &models.MediaLoFi{}
response, err := client.R().
SetBody(lofiAdd).
SetAuthToken(token).
SetHeader("Accept", "application/json").
SetResult(addResult).
Post("http://localhost:8550/api/v1/media/lofis")
if err != nil {
slog.Info("Add Lofi", "error", err.Error())
}
if addResult != nil {
slog.Info("Lofi added", "lofi", addResult)
}
slog.Info("Add Lofi", "status", response.StatusCode(), "body", response.Body)
}
},
}
func init() {
rootCmd.AddCommand(addLinksCmd)
}
+49
View File
@@ -0,0 +1,49 @@
package cmd
import (
"kontor-api-gin/internal/api"
"kontor-api-gin/internal/config"
"log/slog"
"github.com/spf13/cobra"
"resty.dev/v3"
)
type Login struct {
Email string
Password string
}
type LoginResponse struct {
Token string
}
var checkCmd = &cobra.Command{
Use: "check",
Short: "Check Kontor Database",
Long: "Check Kontor Database to given file",
// Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("check kontor")
slog.Info("Verbosity level", "level", config.Verbose)
client := resty.New()
defer client.Close()
localServer := config.Config.Server["local"]
mainServer := config.Config.Server["main"]
localData, _ := api.GetData(localServer, config.Config.ApiVersion)
mainData, _ := api.GetData(mainServer, config.Config.ApiVersion)
slog.Info("comics local", "count", len(localData.Comic))
slog.Info("comics main", "count", len(mainData.Comic))
slog.Info("kontor.check_kontor.check_duplicate_links")
// check_duplicate_links(first_server, dirs)
slog.Info("kontor.check_kontor.check_media_dirs")
// check_media_dirs(first_server, dirs)
},
}
func init() {
rootCmd.AddCommand(checkCmd)
}
+32
View File
@@ -0,0 +1,32 @@
package cmd
import (
"kontor-api-gin/internal/config"
"log/slog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var configCmd = &cobra.Command{
Use: "config",
TraverseChildren: true,
Short: "show current config",
Long: "show current config",
// Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("show config")
var config config.CliConfig
if err := viper.Unmarshal(&config); err != nil {
slog.Info("unable to decode config", "error", err.Error())
}
for name, server := range config.Server {
slog.Info("show config", "server", name, "URL", server.Url)
}
slog.Info("show config", "config", config)
},
}
func init() {
rootCmd.AddCommand(configCmd)
}
+46
View File
@@ -0,0 +1,46 @@
package cmd
import (
"fmt"
"kontor-api-gin/internal/api"
"kontor-api-gin/internal/config"
"log/slog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"resty.dev/v3"
)
var filename string
var exportCmd = &cobra.Command{
Use: "export",
Short: "Export Kontor Database",
Long: "Export Kontor Database to given file",
// Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("export kontor")
slog.Info("Verbosity level", "level", config.Verbose)
slog.Info(fmt.Sprintf("Using server: %s", config.ServerName))
client := resty.New()
defer client.Close()
localServer := config.Config.Server[config.ServerName]
export, _ := api.GetData(localServer, config.Config.ApiVersion)
err := api.WriteJson(export, filename)
if err != nil {
slog.Info("WriteJon failed", "Error:", err)
}
slog.Info("export kontor finished")
},
}
func init() {
rootCmd.AddCommand(exportCmd)
exportCmd.PersistentFlags().StringVarP(&filename, "file", "f", "/home/tpeetz/.sync/media/data-gin.json", "Filename to store data")
viper.BindPFlag("file", exportCmd.PersistentFlags().Lookup("file"))
exportCmd.PersistentFlags().StringVarP(&config.Config.ApiVersion, "api", "a", "api/v1", "API Version")
viper.BindPFlag("api", exportCmd.PersistentFlags().Lookup("api"))
}
+21
View File
@@ -0,0 +1,21 @@
package cmd
import (
"log/slog"
"github.com/spf13/cobra"
)
var importCmd = &cobra.Command{
Use: "import",
Short: "Import Kontor Database",
Long: "Import Kontor Database from given file",
// Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("import kontor")
},
}
func init() {
rootCmd.AddCommand(importCmd)
}
+42
View File
@@ -0,0 +1,42 @@
package cmd
import (
"kontor-api-gin/internal/config"
"log/slog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var configInitcmd = &cobra.Command{
Use: "init",
Short: "create config",
Long: "create config file with defaults",
// Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("create config")
config := config.CliConfig{
Server: map[string]config.Server{
"main": {
Url: "https://kontor-gin.thpeetz.de",
Username: "user",
Password: "password",
},
"local": {
Url: "http://localhost:8550",
Username: "user",
Password: "password",
},
},
}
viper.Set("server", config.Server)
if err := viper.WriteConfig(); err != nil {
slog.Info("write config failed", "error", err.Error())
}
},
}
func init() {
configInitcmd.Flags().BoolVarP(&config.Overwrite, "overwrite", "y", false, "overwrite existing config")
configCmd.AddCommand(configInitcmd)
}
+42
View File
@@ -0,0 +1,42 @@
package cmd
import (
"fmt"
"kontor-api-gin/internal/config"
"log/slog"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "kontor-cli",
TraverseChildren: true,
Short: "A brief description of your application",
Long: ``,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
slog.Info("Verbosity level", "level", config.Verbose)
},
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Oops. An error while executing Zero '%s'\n", err)
os.Exit(1)
}
}
func init() {
rootCmd.PersistentFlags().StringVarP(&config.CfgFile, "config", "c", "/home/tpeetz/.config/kli.yaml", "config file")
rootCmd.PersistentFlags().CountVarP(&config.Verbose, "verbose", "v", "increase verbosity (-v, -vv, -vvv)")
viper.BindPFlag("config", rootCmd.PersistentFlags().Lookup("config"))
exportCmd.Flags().StringVarP(&config.ServerName, "servername", "s", "local", "Define server to get Kontor items")
updateTitleCmd.Flags().StringVarP(&config.ServerName, "servername", "s", "local", "Define server to get Kontor items")
viper.BindPFlag("server", exportCmd.PersistentFlags().Lookup("server"))
cobra.OnInitialize(config.InitCliConfig)
}
+60
View File
@@ -0,0 +1,60 @@
package cmd
import (
"kontor-api-gin/internal/api"
"kontor-api-gin/internal/config"
"log/slog"
"reflect"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var syncCmd = &cobra.Command{
Use: "sync",
Short: "Sync Kontor Database",
Long: "Sync Kontor Database",
// Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
slog.Info("sync kontor")
apiVersion := viper.GetString("api")
mainServer := config.Config.Server["main"]
if config.Verbose > 2 {
slog.Info("syncCmd#Run", "mainServer", mainServer)
}
localServer := config.Config.Server["local"]
sourceData, _ := api.GetData(mainServer, apiVersion)
targetData, _ := api.GetData(localServer, apiVersion)
if config.Verbose > 2 {
slog.Info("Size of targetData", "size", reflect.TypeOf(targetData).Size())
}
slog.Info("iterate sourceData", "table", "Sport", "count", len(sourceData.Sport))
sourceData.Sport.CompareIds(&targetData.Sport)
slog.Info("iterate sourceData", "table", "Player", "count", len(sourceData.Player))
sourceData.Player.CompareIds(&targetData.Player)
slog.Info("iterate sourceData", "table", "MediaLofi", "count source", len(sourceData.MediaLoFi), "count target", len(targetData.MediaLoFi))
missing, obsolete, changed := sourceData.MediaLoFi.CompareIds(&targetData.MediaLoFi)
for _, lofi_id := range missing {
if !config.DryRun {
slog.Info("add MediaLofi", "id", lofi_id)
}
}
for _, lofi_id := range obsolete {
if !config.DryRun {
slog.Info("delete MediaLofi", "id", lofi_id)
api.DeleteData(localServer, "media/lofis", lofi_id)
}
}
for _, lofi_id := range changed {
if !config.DryRun {
slog.Info("update MediaLofi", "id", lofi_id)
// api.UpdateData(localServer, "media/lofis", sourceData.MediaLoFi.GetMediaLofi(lofi_id))
}
}
},
}
func init() {
rootCmd.AddCommand(syncCmd)
syncCmd.PersistentFlags().BoolVarP(&config.DryRun, "dry-run", "m", false, "do not execute data changes")
}
+47
View File
@@ -0,0 +1,47 @@
package cmd
import (
"fmt"
"kontor-api-gin/internal/api"
"kontor-api-gin/internal/config"
"kontor-api-gin/internal/helpers"
"kontor-api-gin/internal/models"
"log/slog"
"github.com/spf13/cobra"
"resty.dev/v3"
)
var updateTitleCmd = &cobra.Command{
Use: "update-title",
Short: "Update titles",
Long: "Update titles",
Run: func(cmd *cobra.Command, args []string) {
slog.Info("Update titles using server", "server", config.ServerName)
client := resty.New()
localServer := config.Config.Server[config.ServerName]
slog.Info("get token", "url", localServer.Url)
token := api.GetToken(client, localServer)
api.GetJSON(client, token, localServer, "media/lofis", &api.Medialofis)
for _, lofi := range api.Medialofis {
if lofi.Review {
title, err := helpers.GetVideoTitle(lofi.WebLink)
var updated models.MediaLoFiDTO
if err != nil {
slog.Info("get title for Url", "url", lofi.WebLink, "error", err.Error())
} else {
slog.Info("get title for Url", "url", lofi.WebLink, "title", title)
lofi.Title = title
lofi.Review = false
api.PostJSON(client, localServer, token, config.Config.ApiVersion, fmt.Sprintf("media/lofis/%s", lofi.ID), lofi, &updated)
slog.Info("MediaLoi updated", "MediaLoFi", updated)
}
}
}
},
}
func init() {
rootCmd.AddCommand(updateTitleCmd)
}
+95
View File
@@ -0,0 +1,95 @@
package config
import (
"fmt"
"log/slog"
"strings"
"github.com/spf13/viper"
)
var (
CfgFile string
Verbose int
Overwrite bool
ServerName string
Config CliConfig
DryRun bool
)
type Server struct {
Url string `mapstructure:"url"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
}
type CliConfig struct {
ApiVersion string
Server map[string]Server `mapstructure:"server"`
}
func InitCliConfig() {
slog.Info("InitCliConfig")
if CfgFile != "" {
viper.SetConfigFile(CfgFile)
} else {
viper.SetConfigName("kli") // without extension
viper.SetConfigType("yaml")
viper.AddConfigPath(".") // look for config in working directory
viper.AddConfigPath("/home/tpeetz/.config")
}
// Read the configuration file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("No config file found, using defaults")
if err := viper.SafeWriteConfig(); err != nil {
slog.Info("error writing config file", "error", err.Error())
}
} else {
slog.Info("error reading config file", "error", err.Error())
}
} else {
slog.Info("initConfig", "Using config file: ", viper.ConfigFileUsed())
if err := viper.Unmarshal(&Config); err != nil {
slog.Info("parsing of config file failed", "error", err.Error())
}
}
}
func InitConfig() error {
viper.SetDefault("db.host", "localhost")
viper.SetDefault("db.port", 5432)
viper.SetDefault("db.name", "kontor")
viper.SetDefault("db.user", "kontor")
viper.SetDefault("db.password", "kontor")
viper.SetDefault("port", 8550)
viper.SetDefault("gin.mode", "release")
viper.SetConfigName("kontor-gin")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("/home/tpeetz/.config")
viper.AddConfigPath("/etc/kontor")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// Read the config file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("No config file found, using defaults")
if err := viper.SafeWriteConfig(); err != nil {
slog.Info("error writing config file", "error", err.Error())
return fmt.Errorf("error writing config file: %w", err)
}
} else {
return fmt.Errorf("error reading config file: %w", err)
}
} else {
slog.Info("initConfig", "Using config file: ", viper.ConfigFileUsed())
}
return nil
}
+35
View File
@@ -0,0 +1,35 @@
package config
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func NewDB(dsn string) (*gorm.DB, error) {
// Configure GORM with custom settings
// The logger helps with debugging SQL queries during development
return gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
// if err != nil {
// log.Fatal("Failed to connect to database:", err)
// }
// // Get the underlying SQL database connection for pool configuration
// sqlDB, err := db.DB()
// if err != nil {
// log.Fatal("Failed to get database instance:", err)
// }
// // Configure connection pool settings
// // MaxIdleConns: number of connections kept open when idle
// sqlDB.SetMaxIdleConns(10)
// // MaxOpenConns: maximum total connections to the database
// sqlDB.SetMaxOpenConns(100)
// // ConnMaxLifetime: how long a connection can be reused
// sqlDB.SetConnMaxLifetime(time.Hour)
// slog.Info("Database connected successfully")
}
+7
View File
@@ -0,0 +1,7 @@
package globals
var Secret = []byte("secret")
const UserKey = "user"
const Version = "0.4.0"
+33
View File
@@ -0,0 +1,33 @@
package handlers
import (
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"gorm.io/gorm"
)
type AdminHandler struct {
AuthHandler *AuthHandler
ProfileHandler *ProfileHandler
PermissionHandler *PermissionHandler
AssignmentHandler *AssignmentHandler
TokenHandler *TokenHandler
MailAccountHandler *MailAccountHandler
MailHandler *MailHandler
Secret []byte
}
func NewAdminHandler(db *gorm.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
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ArticleHandler struct {
Service *service.ArticleService
}
func NewArticleHandler(db *gorm.DB) *ArticleHandler {
handler := &ArticleHandler{Service: service.NewArticleService(repository.NewArticleRepository(db))}
return handler
}
func (handler *ArticleHandler) List(c *gin.Context) {
articles, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertArticlesToDtos(articles)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ArticleAuthorHandler struct {
Service *service.ArticleAuthorService
}
func NewArticleAuthorHandler(db *gorm.DB) *ArticleAuthorHandler {
handler := &ArticleAuthorHandler{Service: service.NewArticleAuthorService(repository.NewArticleAuthorRepository(db))}
return handler
}
func (handler *ArticleAuthorHandler) List(c *gin.Context) {
authors, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertArticleAuthorsToDtos(authors)
c.JSON(http.StatusOK, dtos)
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ArtistHandler struct {
Service *service.ArtistService
}
func NewArtistHandler(db *gorm.DB) *ArtistHandler {
handler := &ArtistHandler{Service: service.NewArtistService(repository.NewArtistRepository(db))}
return handler
}
func (handler *ArtistHandler) List(c *gin.Context) {
artists, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertArtistsToDtos(artists)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type AssignmentHandler struct {
Service *service.AssignmentService
}
func NewAssignmentHandler(db *gorm.DB) *AssignmentHandler {
handler := &AssignmentHandler{Service: service.NewAssignmentService(repository.NewAssignmentRepository(db))}
return handler
}
func (handler *AssignmentHandler) List(c *gin.Context) {
assignments, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertAssignmentsToDtos(assignments)
c.JSON(http.StatusOK, dtos)
}
+128
View File
@@ -0,0 +1,128 @@
package handlers
import (
"kontor-api-gin/internal/globals"
"kontor-api-gin/internal/helpers"
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/slog"
"github.com/gin-gonic/gin"
)
type AuthHandler struct {
Service *service.AuthService
Secret []byte
}
func (handler *AuthHandler) Login(c *gin.Context) {
var input models.LoginInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
proile_id, err := handler.Service.LoginCheck(input.Email, input.Password)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "username or password is incorrect."})
return
}
token, err := helpers.GenerateToken(proile_id)
logger := slog.Get(c)
if err != nil {
logger.Info("Login", "GenerateToken error", err.Error())
}
c.JSON(http.StatusOK, gin.H{"token": token})
}
func (handler *AuthHandler) LoginPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
logger := slog.Get(c)
logger.Info("LoginPage", globals.UserKey, user)
if user != nil {
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "Please logout first",
"user": user,
})
return
}
c.HTML(http.StatusOK, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "",
"user": user,
})
}
func (handler *AuthHandler) LoginPost(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
logger := slog.Get(c)
logger.Info("LoginPost", "user", user)
if user != nil {
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "Please logout first",
})
return
}
username := c.PostForm("username")
password := c.PostForm("password")
if helpers.EmptyUserPass(username, password) {
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "Parameters can't be empty",
})
}
proile_id, err := handler.Service.LoginCheck(username, password)
if err != nil {
c.HTML(http.StatusUnauthorized, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "Incorrect username or password",
})
}
session.Set(globals.UserKey, proile_id)
if err := session.Save(); err != nil {
c.HTML(http.StatusInternalServerError, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "Failed to save session",
})
return
}
logger.Info("LoginPost: redirect to index")
c.Redirect(http.StatusMovedPermanently, "/")
}
func (handler *AuthHandler) LogoutPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
logger := slog.Get(c)
logger.Info("LogoutPage", globals.UserKey, user)
if user == nil {
logger.Info("Invalid session token")
return
}
session.Delete(globals.UserKey)
if err := session.Save(); err != nil {
logger.Info("Failed to save session", "error", err)
return
}
logger.Info("LogoutPage: redirect to index page")
c.Redirect(http.StatusMovedPermanently, "/")
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type AuthorHandler struct {
Service *service.AuthorService
}
func NewAuthorHandler(db *gorm.DB) *AuthorHandler {
handler := &AuthorHandler{Service: service.NewAuthorService(repository.NewAuthorRepository(db))}
return handler
}
func (handler *AuthorHandler) List(c *gin.Context) {
artists, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertAuthorsToDtos(artists)
c.JSON(http.StatusOK, dtos)
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type BookHandler struct {
Service *service.BookService
}
func NewBookHandler(db *gorm.DB) *BookHandler {
handler := &BookHandler{Service: service.NewBookService(repository.NewBookRepository(db))}
return handler
}
func (handler *BookHandler) List(c *gin.Context) {
books, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertBooksToDtos(books)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type BookAuthorHandler struct {
Service *service.BookAuthorService
}
func NewBookAuthorHandler(db *gorm.DB) *BookAuthorHandler {
handler := &BookAuthorHandler{Service: service.NewBookAuthorService(repository.NewBookAuthorRepository(db))}
return handler
}
func (handler *BookAuthorHandler) List(c *gin.Context) {
authors, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertBookAuthorsToDtos(authors)
c.JSON(http.StatusOK, dtos)
}
+26
View File
@@ -0,0 +1,26 @@
package handlers
import (
"gorm.io/gorm"
)
type BookshelfHandler struct {
ArticleHandler *ArticleHandler
BookshelfPublisherHandler *BookshelfPublisherHandler
BookHandler *BookHandler
AuthorHandler *AuthorHandler
ArticleAuthorHandler *ArticleAuthorHandler
BookAuthorHandler *BookAuthorHandler
}
func NewBookshelfHandler(db *gorm.DB) *BookshelfHandler {
bookshelfHandler := &BookshelfHandler{
ArticleHandler: NewArticleHandler(db),
BookshelfPublisherHandler: NewBookshelfPublisherHandler(db),
BookHandler: NewBookHandler(db),
AuthorHandler: NewAuthorHandler(db),
ArticleAuthorHandler: NewArticleAuthorHandler(db),
BookAuthorHandler: NewBookAuthorHandler(db),
}
return bookshelfHandler
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type BookshelfPublisherHandler struct {
Service *service.BookshelfPublisherService
}
func NewBookshelfPublisherHandler(db *gorm.DB) *BookshelfPublisherHandler {
handler := &BookshelfPublisherHandler{Service: service.NewBookshelfPublisherService(repository.NewBookshelfPublisherRepository(db))}
return handler
}
func (handler *BookshelfPublisherHandler) List(c *gin.Context) {
publishers, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertBookshelfPublishersToDtos(publishers)
c.JSON(http.StatusOK, dtos)
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type CardHandler struct {
Service *service.CardService
}
func (handler *CardHandler) List(c *gin.Context) {
cards, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertCardsToDtos(cards)
c.JSON(http.StatusOK, dtos)
}
func (handler *CardHandler) Get(c *gin.Context) {
id := c.Param("id")
card, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "card not found"})
return
}
c.JSON(http.StatusOK, card)
}
func NewCardHandler(db *gorm.DB) *CardHandler {
handler := &CardHandler{Service: service.NewCardService(repository.NewCardRepository(db))}
return handler
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type CardSetHandler struct {
Service *service.CardSetService
}
func (handler *CardSetHandler) List(c *gin.Context) {
cardsets, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertCardSetsToDtos(cardsets)
c.JSON(http.StatusOK, dtos)
}
func (handler *CardSetHandler) Get(c *gin.Context) {
id := c.Param("id")
cardset, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "cardset not found"})
return
}
c.JSON(http.StatusOK, cardset)
}
func NewCardSetHandler(db *gorm.DB) *CardSetHandler {
handler := &CardSetHandler{Service: service.NewCardSetService(repository.NewCardSetRepository(db))}
return handler
}
+78
View File
@@ -0,0 +1,78 @@
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 ComicsHandler struct {
ComicHandler *ComicHandler
PublisherHandler *PublisherHandler
ArtistHandler *ArtistHandler
IssueHandler *IssueHandler
WorkTypeHandler *WorkTypeHandler
VolumeHandler *VolumeHandler
StoryArcHandler *StoryArcHandler
ComicworkHandler *ComicworkHandler
IssueworkHandler *IssueworkHandler
TradePaperbackHandler *TradePaperbackHandler
}
func NewComicsHandler(db *gorm.DB) *ComicsHandler {
comicsHandler := &ComicsHandler{
ComicHandler: NewComicHandler(db),
PublisherHandler: NewPublisherHandler(db),
ArtistHandler: NewArtistHandler(db),
IssueHandler: NewIssueHandler(db),
WorkTypeHandler: NewWorkTypeHandler(db),
VolumeHandler: NewVolumeHandler(db),
StoryArcHandler: NewStoryArcHandler(db),
ComicworkHandler: NewComicworkHandler(db),
IssueworkHandler: NewIssueworkHandler(db),
TradePaperbackHandler: NewTradePaperbackHandler(db),
}
return comicsHandler
}
type ComicHandler struct {
Service *service.ComicService
}
func NewComicHandler(db *gorm.DB) *ComicHandler {
handler := &ComicHandler{Service: service.NewComicService(repository.NewComicRepository(db))}
return handler
}
func (handler *ComicHandler) List(c *gin.Context) {
comics, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertComicsToDtos(comics)
c.JSON(http.StatusOK, dtos)
}
func (handler *ComicHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
comics, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "comics", gin.H{
"title": "Kontor Comics",
"version": "0.4.0",
"message": "Comics...",
"comics": comics,
"user": user,
})
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ComicworkHandler struct {
Service *service.ComicworkService
}
func NewComicworkHandler(db *gorm.DB) *ComicworkHandler {
handler := &ComicworkHandler{Service: service.NewComicworkService(repository.NewComicworkRepository(db))}
return handler
}
func (handler *ComicworkHandler) List(c *gin.Context) {
comicworks, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertComicworksToDtos(comicworks)
c.JSON(http.StatusOK, dtos)
}
+49
View File
@@ -0,0 +1,49 @@
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 IssueHandler struct {
Service *service.IssueService
}
func NewIssueHandler(db *gorm.DB) *IssueHandler {
handler := &IssueHandler{Service: service.NewIssueService(repository.NewIssueRepository(db))}
return handler
}
func (handler *IssueHandler) List(c *gin.Context) {
issues, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertIssuesToDtos(issues)
c.JSON(http.StatusOK, dtos)
}
func (handler *IssueHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
issues, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "Issues", gin.H{
"title": "Kontor Issues",
"version": "0.4.0",
"message": "Issues...",
"issues": issues,
"user": user,
})
}
+49
View File
@@ -0,0 +1,49 @@
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 IssueworkHandler struct {
Service *service.IssueworkService
}
func NewIssueworkHandler(db *gorm.DB) *IssueworkHandler {
handler := &IssueworkHandler{Service: service.NewIssueworkService(repository.NewIssueworkRepository(db))}
return handler
}
func (handler *IssueworkHandler) List(c *gin.Context) {
issueworks, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertIssueworksToDtos(issueworks)
c.JSON(http.StatusOK, dtos)
}
func (handler *IssueworkHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
issueworks, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "Issues", gin.H{
"title": "Kontor Issues",
"version": "0.4.0",
"message": "Issues...",
"issueworks": issueworks,
"user": user,
})
}
+34
View File
@@ -0,0 +1,34 @@
package handlers
import (
"kontor-api-gin/internal/globals"
"net/http"
"time"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/slog"
"github.com/gin-gonic/gin"
)
func Health(c *gin.Context) {
c.JSON(200, gin.H{
"ok": true,
"status": "healthy",
"version": globals.Version,
"time": time.Now().UTC().Format(time.RFC3339),
})
}
func Index(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
logger := slog.Get(c)
logger.Info("IndexGetHandler", globals.UserKey, user)
c.HTML(http.StatusOK, "home", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"message": "This is an index page...",
"user": user,
})
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type MailHandler struct {
Service *service.MailService
}
func NewMailHandler(db *gorm.DB) *MailHandler {
handler := &MailHandler{Service: service.NewMailService(repository.NewMailRepository(db))}
return handler
}
func (handler *MailHandler) List(c *gin.Context) {
mails, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertMailsToDtos(mails)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type MailAccountHandler struct {
Service *service.MailAccountService
}
func NewMailAccountHandler(db *gorm.DB) *MailAccountHandler {
handler := &MailAccountHandler{Service: service.NewMailAccountService(repository.NewMailAccountRepository(db))}
return handler
}
func (handler *MailAccountHandler) List(c *gin.Context) {
mailaccounts, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertMailAccountsToDtos(mailaccounts)
c.JSON(http.StatusOK, dtos)
}
+24
View File
@@ -0,0 +1,24 @@
package handlers
import (
"gorm.io/gorm"
)
type MediaHandler struct {
MediaActorHandler *MediaActorHandler
MediaFileHandler *MediaFileHandler
MediaLoFiHandler *MediaLoFiHandler
MediaVideoHandler *MediaVideoHandler
MediaActorFileHandler *MediaActorFileHandler
}
func NewMediaHandler(db *gorm.DB) *MediaHandler {
mediaHandler := &MediaHandler{
MediaActorHandler: NewMediaActorHandler(db),
MediaFileHandler: NewMediaFileHandler(db),
MediaLoFiHandler: NewMediaLoFiHandler(db),
MediaVideoHandler: NewMediaVideoHandler(db),
MediaActorFileHandler: NewMediaActorFileHandler(db),
}
return mediaHandler
}
@@ -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 MediaActorHandler struct {
Service *service.MediaActorService
}
func NewMediaActorHandler(db *gorm.DB) *MediaActorHandler {
mediaActorHandler := &MediaActorHandler{
Service: service.NewMediaActorService(repository.NewMediaActorRepository(db)),
}
return mediaActorHandler
}
func (handler *MediaActorHandler) List(c *gin.Context) {
lofis, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertMediaActorsToDtos(lofis)
c.JSON(http.StatusOK, dtos)
}
func (handler *MediaActorHandler) 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 *MediaActorHandler) Add(c *gin.Context) {
var input models.MediaActorAdd
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
actor, err := handler.Service.Add(c.Request.Context(), input.WebLink)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "lofi not added"})
return
}
c.JSON(http.StatusOK, actor)
}
func (handler *MediaActorHandler) 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 *MediaActorHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
actors, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "mediaactors", gin.H{
"title": "Kontor MediaActors",
"version": "0.4.0",
"message": "MediaActors...",
"actors": actors,
"user": user,
})
}
@@ -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,
})
}
@@ -0,0 +1,79 @@
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 MediaFileHandler struct {
Service *service.MediaFileService
}
func NewMediaFileHandler(db *gorm.DB) *MediaFileHandler {
mediaFileHandler := &MediaFileHandler{
Service: service.NewMediaFileService(repository.NewMediaFileRepository(db)),
}
return mediaFileHandler
}
func (handler *MediaFileHandler) List(c *gin.Context) {
logger := slog.Get(c)
logger.Info("MediaFileHandler#List")
files, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertMediaFilesToDtos(files)
c.JSON(http.StatusOK, dtos)
}
func (handler *MediaFileHandler) Add(c *gin.Context) {
var input models.MediaFileAdd
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
lofi, err := handler.Service.Add(c.Request.Context(), input.Url)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "lofi not added"})
return
}
c.JSON(http.StatusOK, lofi)
}
func (handler *MediaFileHandler) 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": "lofi not found"})
return
}
c.JSON(http.StatusOK, gin.H{"ok": "true"})
}
func (handler *MediaFileHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
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, "mediafiles", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"mediafiles": files,
"user": user,
})
}
+205
View File
@@ -0,0 +1,205 @@
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 MediaLoFiHandler struct {
Service *service.MediaLoFiService
}
func NewMediaLoFiHandler(db *gorm.DB) *MediaLoFiHandler {
mediaLoFiHandler := &MediaLoFiHandler{
Service: service.NewMediaLoFiService(repository.NewMediaLoFiRepository(db)),
}
return mediaLoFiHandler
}
func (handler *MediaLoFiHandler) List(c *gin.Context) {
lofis, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertMediaLoFisToDtos(lofis)
c.JSON(http.StatusOK, dtos)
}
func (handler *MediaLoFiHandler) Get(c *gin.Context) {
id := c.Param("id")
lofi, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Lofi not found"})
return
}
c.JSON(http.StatusOK, lofi)
}
func (handler *MediaLoFiHandler) 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
}
lofi, err := handler.Service.Add(c.Request.Context(), input.Url)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "lofi not added"})
return
}
c.JSON(http.StatusOK, lofi)
}
func (handler *MediaLoFiHandler) Update(c *gin.Context) {
var input models.MediaLoFiDTO
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
lofi, err := handler.Service.Update(c.Request.Context(), input)
if err != nil {
logger := slog.Get(c)
logger.Info("MediaLoFiHandler#Update", "error", err.Error())
c.JSON(http.StatusNotFound, gin.H{"error": "lofi not updated"})
return
}
c.JSON(http.StatusOK, lofi)
}
func (handler *MediaLoFiHandler) 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": "lofi not found"})
return
}
c.JSON(http.StatusOK, gin.H{"ok": "true"})
}
func (handler *MediaLoFiHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
logger := slog.Get(c)
lofis, err := handler.Service.List(c.Request.Context())
if err != nil {
logger.Info("MediaLoFiHandler#ListPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
c.HTML(http.StatusOK, "lofi", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"lofis": lofis,
"user": user,
})
}
func (handler *MediaLoFiHandler) EditPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
lofi, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#EditPage", "lofi", lofi)
c.HTML(http.StatusOK, "lofi_detail", gin.H{
"title": "Kontor MediaFLofi",
"version": "0.4.0",
"message": "MediaFiles...",
"lofi": lofi,
"user": user,
})
}
func (handler *MediaLoFiHandler) ChangeReviewPage(c *gin.Context) {
id := c.Param("id")
logger := slog.Get(c)
lofi, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
c.Redirect(http.StatusNotFound, "/web/media-lofis")
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, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
c.HTML(http.StatusOK, "lofi", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"lofis": lofis,
"user": user,
})
c.Redirect(http.StatusCreated, "/web/media-lofis")
}
func (handler *MediaLoFiHandler) UpdatePage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
lofi, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var form models.MediaLoFiForm
if err := c.ShouldBind(&form); err != nil {
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
c.HTML(http.StatusBadRequest, "lofi_detail", gin.H{
"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, "web/media-lofis")
}
func (handler *MediaLoFiHandler) DeletePage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
lofi, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#DeletePage", "lofi", id)
c.HTML(http.StatusOK, "lofi_delete", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"lofi": lofi,
"user": user,
})
}
@@ -0,0 +1,52 @@
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)
videos, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "mediavideos", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"mediavideos": videos,
"user": user,
})
}
@@ -0,0 +1,21 @@
package handlers
import (
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
)
type PermissionHandler struct {
Service *service.PermissionService
}
func (handler *PermissionHandler) List(c *gin.Context) {
permissions, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, permissions)
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type PlayerHandler struct {
Service *service.PlayerService
}
func (handler *PlayerHandler) List(c *gin.Context) {
players, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertPlayersToDtos(players)
c.JSON(http.StatusOK, dtos)
}
func (handler *PlayerHandler) Get(c *gin.Context) {
id := c.Param("id")
player, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "player not found"})
return
}
c.JSON(http.StatusOK, player)
}
func NewPlayerHandler(db *gorm.DB) *PlayerHandler {
handler := &PlayerHandler{Service: service.NewPlayerService(repository.NewPlayerRepository(db))}
return handler
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type PositionHandler struct {
Service *service.PositionService
}
func (handler *PositionHandler) List(c *gin.Context) {
positions, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertPositionsToDtos(positions)
c.JSON(http.StatusOK, dtos)
}
func (handler *PositionHandler) Get(c *gin.Context) {
id := c.Param("id")
position, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "position not found"})
return
}
c.JSON(http.StatusOK, position)
}
func NewPositionHandler(db *gorm.DB) *PositionHandler {
handler := &PositionHandler{Service: service.NewPositionService(repository.NewPositionRepository(db))}
return handler
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ProfileHandler struct {
Service *service.ProfileService
}
func NewProfileHandler(db *gorm.DB) *ProfileHandler {
handler := &ProfileHandler{Service: service.NewProfileService(repository.NewProfileRepository(db))}
return handler
}
func (handler *ProfileHandler) List(c *gin.Context) {
profiles, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertProfilesToDtos(profiles)
c.JSON(http.StatusOK, dtos)
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type PublisherHandler struct {
Service *service.PublisherService
}
func NewPublisherHandler(db *gorm.DB) *PublisherHandler {
handler := &PublisherHandler{Service: service.NewPublisherService(repository.NewPublisherRepository(db))}
return handler
}
func (handler *PublisherHandler) List(c *gin.Context) {
comics, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertPublishersToDtos(comics)
c.JSON(http.StatusOK, dtos)
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type RoosterHandler struct {
Service *service.RoosterService
}
func (handler *RoosterHandler) List(c *gin.Context) {
roosters, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertRoostersToDtos(roosters)
c.JSON(http.StatusOK, dtos)
}
func (handler *RoosterHandler) Get(c *gin.Context) {
id := c.Param("id")
rooster, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "rooster not found"})
return
}
c.JSON(http.StatusOK, rooster)
}
func NewRoosterHandler(db *gorm.DB) *RoosterHandler {
handler := &RoosterHandler{Service: service.NewRoosterService(repository.NewRoosterRepository(db))}
return handler
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type SportHandler struct {
Service *service.SportService
}
func (handler *SportHandler) List(c *gin.Context) {
sports, _, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertSportsToDtos(sports)
c.JSON(http.StatusOK, dtos)
}
func (handler *SportHandler) Get(c *gin.Context) {
id := c.Param("id")
sport, 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, sport)
}
func NewSportHandler(db *gorm.DB) *SportHandler {
handler := &SportHandler{Service: service.NewSportService(repository.NewSportRepository(db))}
return handler
}
+49
View File
@@ -0,0 +1,49 @@
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 StoryArcHandler struct {
Service *service.StoryArcService
}
func NewStoryArcHandler(db *gorm.DB) *StoryArcHandler {
handler := &StoryArcHandler{Service: service.NewStoryArcService(repository.NewStoryArcRepository(db))}
return handler
}
func (handler *StoryArcHandler) List(c *gin.Context) {
storyArcs, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertStoryArcsToDtos(storyArcs)
c.JSON(http.StatusOK, dtos)
}
func (handler *StoryArcHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
storyArcs, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "StoryArcs", gin.H{
"title": "Kontor StoryArcs",
"version": "0.4.0",
"message": "StoryArcs...",
"storyArcs": storyArcs,
"user": user,
})
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type TeamHandler struct {
Service *service.TeamService
}
func (handler *TeamHandler) List(c *gin.Context) {
teams, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertTeamsToDtos(teams)
c.JSON(http.StatusOK, dtos)
}
func (handler *TeamHandler) Get(c *gin.Context) {
id := c.Param("id")
team, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "team not found"})
return
}
c.JSON(http.StatusOK, team)
}
func NewTeamHandler(db *gorm.DB) *TeamHandler {
handler := &TeamHandler{Service: service.NewTeamService(repository.NewTeamRepository(db))}
return handler
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type TokenHandler struct {
Service *service.TokenService
}
func NewTokenHandler(db *gorm.DB) *TokenHandler {
handler := &TokenHandler{Service: service.NewTokenService(repository.NewTokenRepository(db))}
return handler
}
func (handler *TokenHandler) List(c *gin.Context) {
tokens, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertTokensToDtos(tokens)
c.JSON(http.StatusOK, dtos)
}
@@ -0,0 +1,49 @@
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 TradePaperbackHandler struct {
Service *service.TradePaperbackService
}
func NewTradePaperbackHandler(db *gorm.DB) *TradePaperbackHandler {
handler := &TradePaperbackHandler{Service: service.NewTradePaperbackService(repository.NewTradePaperbackRepository(db))}
return handler
}
func (handler *TradePaperbackHandler) List(c *gin.Context) {
tradepaperbacks, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertTradePaperbacksToDtos(tradepaperbacks)
c.JSON(http.StatusOK, dtos)
}
func (handler *TradePaperbackHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
tradepaperbacks, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "comics", gin.H{
"title": "Kontor Comics",
"version": "0.4.0",
"message": "Comics...",
"tradepaperbacks": tradepaperbacks,
"user": user,
})
}
+30
View File
@@ -0,0 +1,30 @@
package handlers
import (
"gorm.io/gorm"
)
type TyscHandler struct {
SportHandler *SportHandler
PlayerHandler *PlayerHandler
TeamHandler *TeamHandler
PositionHandler *PositionHandler
RoosterHandler *RoosterHandler
VendorHandler *VendorHandler
CardSetHandler *CardSetHandler
CardHandler *CardHandler
}
func NewTyscHandler(db *gorm.DB) *TyscHandler {
handlerMap := &TyscHandler{
SportHandler: NewSportHandler(db),
PlayerHandler: NewPlayerHandler(db),
TeamHandler: NewTeamHandler(db),
PositionHandler: NewPositionHandler(db),
RoosterHandler: NewRoosterHandler(db),
VendorHandler: NewVendorHandler(db),
CardSetHandler: NewCardSetHandler(db),
CardHandler: NewCardHandler(db),
}
return handlerMap
}
+40
View File
@@ -0,0 +1,40 @@
package handlers
import (
"kontor-api-gin/internal/models"
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type VendorHandler struct {
Service *service.VendorService
}
func (handler *VendorHandler) List(c *gin.Context) {
vendors, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertVendorsToDtos(vendors)
c.JSON(http.StatusOK, dtos)
}
func (handler *VendorHandler) Get(c *gin.Context) {
id := c.Param("id")
vendor, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "vendor not found"})
return
}
c.JSON(http.StatusOK, vendor)
}
func NewVendorHandler(db *gorm.DB) *VendorHandler {
handler := &VendorHandler{Service: service.NewVendorService(repository.NewVendorRepository(db))}
return handler
}
+49
View File
@@ -0,0 +1,49 @@
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 VolumeHandler struct {
Service *service.VolumeService
}
func NewVolumeHandler(db *gorm.DB) *VolumeHandler {
handler := &VolumeHandler{Service: service.NewVolumeService(repository.NewVolumeRepository(db))}
return handler
}
func (handler *VolumeHandler) List(c *gin.Context) {
volumes, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertVolumesToDtos(volumes)
c.JSON(http.StatusOK, dtos)
}
func (handler *VolumeHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
volumes, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "Volumes", gin.H{
"title": "Kontor Volumes",
"version": "0.4.0",
"message": "Volumes...",
"volumes": volumes,
"user": user,
})
}
+21
View File
@@ -0,0 +1,21 @@
package handlers
import (
"kontor-api-gin/internal/repository"
"kontor-api-gin/internal/service"
"gorm.io/gorm"
)
type WebAppHandler struct {
AuthHandler *AuthHandler
ComicHandler *ComicHandler
}
func NewWebAppHandler(db *gorm.DB, secret []byte) *WebAppHandler {
webapp := &WebAppHandler{
AuthHandler: &AuthHandler{Service: service.NewAuthService(repository.NewProfileRepository(db), secret)},
ComicHandler: &ComicHandler{Service: service.NewComicService(repository.NewComicRepository(db))},
}
return webapp
}
+49
View File
@@ -0,0 +1,49 @@
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 WorkTypeHandler struct {
Service *service.WorkTypeService
}
func NewWorkTypeHandler(db *gorm.DB) *WorkTypeHandler {
handler := &WorkTypeHandler{Service: service.NewWorkTypeService(repository.NewWorkTypeRepository(db))}
return handler
}
func (handler *WorkTypeHandler) List(c *gin.Context) {
workTypes, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
dtos := models.ConvertWorkTypesToDtos(workTypes)
c.JSON(http.StatusOK, dtos)
}
func (handler *WorkTypeHandler) ListPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
workTypes, err := handler.Service.List(c.Request.Context())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "WorkTypes", gin.H{
"title": "Kontor WorkTypes",
"version": "0.4.0",
"message": "WorkTypes...",
"workTypes": workTypes,
"user": user,
})
}
+13
View File
@@ -0,0 +1,13 @@
package helpers
import (
"strings"
)
func CheckUserPass(username, password string) bool {
return true
}
func EmptyUserPass(username, password string) bool {
return strings.Trim(username, " ") == "" || strings.Trim(password, " ") == ""
}
+27
View File
@@ -0,0 +1,27 @@
package helpers
import (
"bufio"
"os"
)
func LinesInFile(fileName string) ([]string, error) {
f, err := os.Open(fileName)
if err != nil {
return nil, err
}
defer f.Close()
// Create new Scanner.
scanner := bufio.NewScanner(f)
result := []string{}
// Use Scan.
for scanner.Scan() {
line := scanner.Text()
// Append line to result.
result = append(result, line)
}
if err := scanner.Err(); err != nil {
return nil, err
}
return result, nil
}

Some files were not shown because too many files have changed in this diff Show More