ADD: added basic backend function plus a mockup for a cli interface

This commit is contained in:
2025-12-13 21:44:48 +01:00
parent c6de2481e6
commit a047d57824
21 changed files with 657 additions and 51 deletions

View File

@@ -17,7 +17,7 @@ type LoginRequest struct {
var secret = []byte("secret")
func LoginHandler(c *gin.Context, db *sql.DB) {
func Login(c *gin.Context, db *sql.DB) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})

View File

@@ -0,0 +1,48 @@
package config
import (
"os"
)
type Config struct {
Port string
Env string
DatabaseDriver string
DatabaseHost string
DatabasePort string
DatabaseName string
DatabaseUser string
DatabasePassword string
FrontendURL string
}
func New() *Config {
return generateConfig()
}
func generateConfig() *Config {
cfg := Config{
Port: getEnv("PORT", "8080"),
DatabaseDriver: getEnv("DB_DRIVER", "postgres"),
DatabaseHost: getEnv("database", "localhost"),
DatabasePort: getEnv("DB_PORT", "5432"),
DatabaseName: getEnv("DB_NAME", "studia"),
DatabaseUser: getEnv("DB_USER", "user"),
DatabasePassword: getEnv("DB_PASSWORD", "password"),
Env: getEnv("ENV", "development"),
FrontendURL: getEnv("FRONTEND_URL", "http://localhost:5173"),
}
return &cfg
}
// helper function to get env var or default
func getEnv(key, defaultVal string) string {
value, exists := os.LookupEnv(key)
if !exists || value == "" {
return defaultVal
}
return value
}

View File

@@ -0,0 +1,97 @@
package database
import (
"database/sql"
"fmt"
"log"
"studia/internal/config"
_ "github.com/lib/pq" // Import the PostgreSQL driver
)
var expectedTables = []string{
"users",
}
func New(cfg *config.Config) *sql.DB {
db := setupDatabase(cfg)
existing, err := getExistingTables(db, `
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
`)
if err != nil {
log.Println("failed to query existing tables:", err)
}
missing := checkTables(expectedTables, existing)
if len(missing) > 0 {
log.Println("Missing tables detected:", missing)
// Here you would normally run migrations to create the missing tables
// For simplicity, we just log the missing tables
} else {
log.Println("All expected tables are present.")
}
return db
}
func setupDatabase(cfg *config.Config) *sql.DB {
// Database connection setup logic here
log.Println(cfg)
switch cfg.DatabaseDriver {
case "postgres":
// Setup Postgres connection
log.Println("Setting up Postgres connection")
psqlInfo := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
cfg.DatabaseHost, cfg.DatabasePort, cfg.DatabaseUser, cfg.DatabasePassword, cfg.DatabaseName)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatal("Failed to connect to database:", err)
}
return db
case "mysql":
// Setup MySQL connection
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s",
cfg.DatabaseUser, cfg.DatabasePassword, cfg.DatabaseHost, cfg.DatabasePort, cfg.DatabaseName)
db, err := sql.Open("mysql", dsn)
if err != nil {
// Handle error
}
return db
default:
// Handle unsupported database driver
}
return nil
}
func getExistingTables(db *sql.DB, query string) (map[string]bool, error) {
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
tables := make(map[string]bool)
for rows.Next() {
var name string
if err := rows.Scan(&name); err != nil {
return nil, err
}
tables[name] = true
}
return tables, nil
}
func checkTables(expected []string, existing map[string]bool) []string {
var missing []string
for _, table := range expected {
if !existing[table] {
missing = append(missing, table)
}
}
return missing
}

View File

@@ -1,26 +1,60 @@
package server
import (
"fmt"
"log"
"os"
"studia/internal/auth"
"studia/internal/config"
"studia/internal/database"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
var secret = []byte("secret")
func StartServer(cfg *config.Config) {
func StartServer() {
router := gin.Default()
r := gin.Default()
db := database.New(cfg)
r.POST("/login", func(c *gin.Context) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user": "demo",
"role": "admin",
"exp": time.Now().Add(24 * time.Hour).Unix(),
})
signed, _ := token.SignedString(secret)
c.JSON(200, gin.H{"token": signed})
// 2. CORS-Konfiguration
// Lese die Frontend-URL aus den Umgebungsvariablen
frontendURL := os.Getenv("FRONTEND_URL")
// Lokaler Fallback (wichtig für die Entwicklung)
allowedOrigins := []string{
"http://localhost:5173", // Gängiger Vite-Dev-Port
}
if frontendURL != "" {
allowedOrigins = append(allowedOrigins, frontendURL)
fmt.Printf("CORS: Erlaubte Produktiv-URL hinzugefügt: %s\n", frontendURL)
} else {
log.Println("ACHTUNG: FRONTEND_URL fehlt in den Umgebungsvariablen. Nur lokale URLs erlaubt.")
}
// CORS
// Konfiguriere die CORS-Middleware
config := cors.Config{
// Setze die erlaubten Ursprünge (deine React-URLs)
AllowOrigins: allowedOrigins,
// Erlaube die notwendigen HTTP-Methoden
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"},
// Erlaube Header (z.B. für JSON und Authentifizierung)
AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"},
// Erlaube Cookies und Credentials (falls du Tokens oder Sessions nutzt)
AllowCredentials: true,
// Wie lange die Preflight-Anfrage (OPTIONS) gecacht werden darf
MaxAge: 12 * time.Hour,
}
router.Use(cors.New(config))
router.POST("/login", func(c *gin.Context) {
auth.Login(c, db) // Pass the actual DB connection instead of nil
})
router.Run(":" + cfg.Port)
}