add subproject kontor-gin
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s

This commit is contained in:
Thomas Peetz
2026-09-18 17:42:50 +02:00
parent c1d913e36b
commit 8f5a384e89
10 changed files with 458 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
package handlers
import (
"kontor-api-gin/pkg/schema"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func ListMediaFiles(c *gin.Context) {
var files []schema.MediaFile
// query := schema.DB.Model(&schema.MediaFile{})
// result := query.Find(&files)
result := schema.DB.Find(&files)
log.Printf("found %d MediaFiles", result.RowsAffected)
c.JSON(http.StatusOK, gin.H{
"message": "All MediaFiles",
"files": files,
})
}
+10
View File
@@ -0,0 +1,10 @@
package routes
import (
"github.com/gin-gonic/gin"
)
func SetupApiRoutes(router *gin.Engine) *gin.RouterGroup {
v1 := router.Group("api/v1")
return v1
}
+16
View File
@@ -0,0 +1,16 @@
package routes
import (
"kontor-api-gin/pkg/handlers"
"github.com/gin-gonic/gin"
)
func SetupMediaRoutes(router *gin.RouterGroup) {
media := router.Group("/media")
files := media.Group("/files")
{
files.GET("", handlers.ListMediaFiles)
}
}
+22
View File
@@ -0,0 +1,22 @@
package schema
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type Base struct {
ID string `gorm:"type:string;primary_key;"`
CreatedAt time.Time `json:"created_date"`
UpdatedAt time.Time `json:"last_modified_date"`
DeletedAt *time.Time `json:"deleted_date"`
Version int `gorm:"default:0" json:"version"`
}
// BeforeCreate will set a UUID rather than numeric ID.
func (b *Base) BeforeCreate(tx *gorm.DB) (err error) {
b.ID = uuid.New().String()
return
}
+69
View File
@@ -0,0 +1,69 @@
package schema
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var DB *gorm.DB
func Connect() {
// Build the connection string from environment variables
// This keeps sensitive credentials out of the codebase
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
os.Getenv("DB_HOST"),
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_NAME"),
os.Getenv("DB_PORT"),
)
// Configure GORM with custom settings
// The logger helps with debugging SQL queries during development
db, err := 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)
DB = db
log.Println("Database connected successfully")
}
func RunMigrations() {
// AutoMigrate creates tables, missing columns, and missing indexes
// It will NOT delete unused columns to protect your data
err := DB.AutoMigrate(
&MediaActor{},
&MediaFile{},
&MediaActorFile{},
)
if err != nil {
log.Fatal("Migration failed:", err)
}
log.Println("Database migration completed")
}
+76
View File
@@ -0,0 +1,76 @@
package schema
import (
)
type MediaFile struct {
Base
CloudLink string `json:"cloud_link"`
FileName string `json:"file_name"`
Path string `json:"path"`
Review bool `json:"review"`
Title string `gorm:"size:300" json:"title"`
WebLink string `gorm:"uniqueIndex" json:"url"`
ShouldDownload bool `json:"should_download"`
MediaActorFiles []MediaActorFile `gorm:"foreignKey:MediaFileID" json:"media_actor_files"`
}
func (media_file *MediaFile) TableName() string {
return "media_file"
}
type MediaActor struct {
Base
Name string `json:"name"`
WebLink string `gorm:"uniqueIndex" json:"url"`
MediaActorFiles []MediaActorFile `gorm:"foreignKey:MediaActorID" json:"media_actor_files"`
}
func (media_actor *MediaActor) TableName() string {
return "media_actor"
}
type MediaActorFile struct {
Base
MediaActorID *string `json:"media_actor_id"`
MediaActor *MediaActor `gorm:"foreignKey:MediaActorID" json:"media_actor"`
MediaFileID *string `json:"media_file_id"`
MediaFile *MediaFile `gorm:"foreignKey:MediaFileID" json:"media_file"`
}
func (media_file *MediaActorFile) TableName() string {
return "media_actor_file"
}
// type MediaArticle struct {
// bun.BaseModel `bun:"table:media_article"`
// ID string `bun:"id,pk"`
// CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
// UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
// Version int `bun:"version,default:0"`
// Review bool `bun:"review"`
// Title string `bun:"title"`
// WebLink string `bun:"url,unique:url"`
// }
// type MediaVideo struct {
// bun.BaseModel `bun:"table:media_article"`
// ID string `bun:"id,pk"`
// CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
// UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
// Version int `bun:"version,default:0"`
// CloudLink string `bun:"cloud_link"`
// FileName string `bun:"file_name"`
// Path string `bun:"path"`
// Review bool `bun:"review"`
// Title string `bun:"title"`
// WebLink string `bun:"url,unique:url"`
// ShouldDownload bool `bun:"should_download"`
// }