Bulk commit: November work

This commit is contained in:
2025-11-06 11:46:35 +01:00
parent cf82dede3b
commit 183875baf4
60 changed files with 16590 additions and 102 deletions

View File

@ -1,20 +1,84 @@
package utils
import (
"context"
"errors"
"log/slog"
"strconv"
"time"
glide "github.com/valkey-io/valkey-glide/go/v2"
"gorm.io/gorm"
)
type Application struct {
Logger *slog.Logger
DB *gorm.DB
ActiveSessions []Session
Logger *slog.Logger
DB *gorm.DB
Client *glide.Client
}
type Session struct {
Token string
UserID uint
CreatedAt time.Time
MandantId uint
}
func (s *Session) Deserialize(t string, m map[string]string) (*Session, error) {
userid, err := strconv.Atoi(m["userid"])
if err != nil {
return nil, errors.New("Userid from cache not an int")
}
mandantid, err := strconv.Atoi(m["mandantid"])
if err != nil {
return nil, errors.New("Mandantid from cache not an int")
}
s.Token = t
s.UserID = uint(userid)
s.MandantId = uint(mandantid)
return s, nil
}
func (s *Session) Serialize() map[string]string {
m := make(map[string]string)
m["userid"] = strconv.Itoa(int(s.UserID))
m["mandantid"] = strconv.Itoa(int(s.MandantId))
return m
}
func (a *Application) AddSession(s *Session) {
// options.HSetExOptions{Expiry: options.NewExpiryIn(time.Hour * 2)}
_, err := a.Client.HSet(context.Background(), s.Token, s.Serialize())
if err != nil {
panic(err)
}
_, err = a.Client.Expire(context.Background(), s.Token, time.Hour*2)
if err != nil {
panic(err)
}
}
func (a *Application) GetSessionFromToken(token string) (*Session, error) {
s, err := a.Client.HGetAll(context.Background(), token)
if err != nil {
panic(err)
}
_, err = a.Client.Expire(context.Background(), token, time.Hour*2)
if err != nil {
panic(err)
}
return (&Session{}).Deserialize(token, s)
}
func (a *Application) RemoveSession(token string) {
_, err := a.Client.HDel(context.Background(), token, []string{"userid", "mandantid"})
if err != nil {
panic(err)
}
}

View File

@ -2,10 +2,9 @@ package utils
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"slices"
"time"
"git.kocoder.xyz/kocoded/vt/model"
@ -31,6 +30,9 @@ func setCallbackCookieExp(w http.ResponseWriter, r *http.Request, name, value st
http.SetCookie(w, c)
}
type Info struct {
}
func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
provider, err := oidc.NewProvider(ctx, "https://keycloak.kocoder.xyz/realms/che")
if err != nil {
@ -40,7 +42,7 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
oauthConfig := oauth2.Config{
ClientID: os.Getenv("CLIENT_ID"),
ClientSecret: os.Getenv("CLIENT_SECRET"),
RedirectURL: "http://localhost:3000/api/auth/callback",
RedirectURL: os.Getenv("BACKEND_URI") + "/api/auth/callback",
Endpoint: provider.Endpoint(),
@ -92,15 +94,15 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
UserInfo *oidc.UserInfo
}{oauth2Token, userInfo}
data, err := json.MarshalIndent(resp, "", " ")
claims := &model.User{}
err = resp.UserInfo.Claims(claims)
if err != nil {
appCtx.Logger.Warn("Failed to parse JSON", "error", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
panic(err)
}
fmt.Println(claims)
user := &model.User{}
if appCtx.DB.Where(model.User{Email: resp.UserInfo.Email}).Assign(model.User{Sub: resp.UserInfo.Subject}).FirstOrCreate(user).Error != nil {
if appCtx.DB.Where(model.User{Email: resp.UserInfo.Email}).Assign(claims).FirstOrCreate(user).Error != nil {
appCtx.Logger.Warn("Failed to create user in DB")
http.Error(w, "failed to create user", http.StatusInternalServerError)
return
@ -116,25 +118,56 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
}
setCallbackCookieExp(w, r, "auth-cookie", cookie, int(time.Hour.Seconds()))
appCtx.ActiveSessions = append(appCtx.ActiveSessions, Session{Token: cookie, UserID: user.ID, CreatedAt: time.Now()})
appCtx.AddSession(&Session{Token: cookie, UserID: user.ID, MandantId: 1})
http.Redirect(w, r, "http://localhost:3001", http.StatusFound)
_, err = w.Write(data)
if err != nil {
appCtx.Logger.Error("Unable to send response", "error", err)
}
http.Redirect(w, r, os.Getenv("FRONTEND_URI")+"/dashboard", http.StatusFound)
}))
app.Get("/api/auth/currentSession", func(c *fiber.Ctx) error {
authToken := c.Cookies("auth-cookie")
sessionId := slices.IndexFunc(appCtx.ActiveSessions, func(s Session) bool {
return s.Token == authToken
})
session := appCtx.ActiveSessions[sessionId]
session, err := appCtx.GetSessionFromToken(authToken)
if err != nil {
return err
}
return c.JSON(session)
})
app.Get("/api/auth/logout", func(c *fiber.Ctx) error {
authToken := c.Cookies("auth-cookie")
appCtx.RemoveSession(authToken)
cookie := new(fiber.Cookie)
cookie.Name = "auth-cookie"
cookie.Expires = time.Now().Add(-1 * time.Minute)
c.Cookie(cookie)
return c.Redirect(os.Getenv("FRONTEND_URI"))
})
}
type keyType struct{}
var UserKey keyType
func IsAuthenticated(appCtx Application) fiber.Handler {
fmt.Println("Gettings Session")
return func(c *fiber.Ctx) error {
authToken := c.Cookies("auth-cookie")
fmt.Println("Gettings Session", "sessiontoken", authToken)
session, err := appCtx.GetSessionFromToken(authToken)
if err != nil {
appCtx.Logger.Warn("Unauthorized GET Attempt", "reason", err)
return c.SendStatus(fiber.StatusUnauthorized)
}
fmt.Println("Saving Session", "session", session)
c.Locals("USER_KEY", session)
return c.Next()
}
}

35
utils/cache.go Normal file
View File

@ -0,0 +1,35 @@
package utils
import (
"context"
"fmt"
"strconv"
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func SetupCache(host, port, user, pass string) (*glide.Client, bool) {
p, err := strconv.Atoi(port)
if err != nil {
fmt.Println("VALKEY_PORT is not a number")
return nil, false
}
config := config.NewClientConfiguration().WithAddress(&config.NodeAddress{Host: host, Port: p}).WithCredentials(config.NewServerCredentials(user, pass))
client, err := glide.NewClient(config)
if err != nil {
fmt.Println("There was an error: ", err)
return nil, false
}
res, err := client.Ping(context.Background())
if err != nil {
fmt.Println("There was an error: ", err)
return nil, false
}
fmt.Println(res) // PONG
return client, true
}

View File

@ -24,13 +24,13 @@ func SetupDatabase(dsn string, logger *slog.Logger) *gorm.DB {
if err != nil {
logger.Error("Error setting up Join Tables", "error", err)
}
err = db.AutoMigrate(&model.Mandant{}, &model.User{}, &model.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{})
err = db.AutoMigrate(&model.Mandant{}, &model.User{}, &model.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{}, &model.Projekt{})
if err != nil {
logger.Error("Error setting up Join Tables", "error", err)
}
g := gen.NewGenerator(gen.Config{
OutPath: "./query",
OutPath: "query",
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
})

68
utils/messagebus.go Normal file
View File

@ -0,0 +1,68 @@
package utils
import (
"encoding/json"
"io"
"log/slog"
"github.com/gofiber/contrib/websocket"
)
var MessageBus = &messagebus{mandanten: make(map[int][]*websocket.Conn)}
type messagebus struct {
mandanten map[int][]*websocket.Conn
}
func (mb *messagebus) AddConn(mid int, c *websocket.Conn) {
mb.mandanten[mid] = append(mb.mandanten[mid], c)
ReadLoop(c)
}
func ReadLoop(c *websocket.Conn) {
for {
var t int
var r io.Reader
var err error
if t, r, err = c.NextReader(); err != nil {
c.Close()
break
}
bytes, err := io.ReadAll(r)
slog.Info("READLOOP: ", "Type", t, "value", bytes)
}
}
func (mb *messagebus) SendMBObject(mid int, mbo MessageBusObject) {
bytes, err := json.Marshal(mbo)
if err != nil {
slog.Info("marshal", "error", err)
}
i := 0
for _, c := range mb.mandanten[mid] {
if err := c.WriteMessage(websocket.TextMessage, bytes); err != nil {
slog.Info("conn to remove", "conns", mb.mandanten)
mb.RemoveConn(mid, i)
slog.Info("write", "error", err, "index", i)
} else {
i++
}
}
}
func (mb *messagebus) RemoveConn(mid int, i int) {
s := mb.mandanten[mid]
s[i] = s[len(s)-1]
mb.mandanten[mid] = s[:len(s)-1]
slog.Info("conn removed", "conns", mb.mandanten)
}
type MessageBusObject struct {
Entity []string `json:"entity"`
Id any `json:"id"`
}

View File

@ -1,6 +1,8 @@
package utils
import (
"os"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/cors"
@ -19,7 +21,7 @@ func RegisterMiddlewares(app *fiber.App) {
app.Use(compress.New())
app.Use(helmet.New())
app.Use(cors.New(cors.Config{
AllowOrigins: "http://localhost:3000, http://localhost:3001",
AllowOrigins: os.Getenv("FRONTEND_URI"),
AllowCredentials: true,
}))
// app.Use(csrf.New())