Bulk commit
This commit is contained in:
@ -2,11 +2,19 @@ package utils
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
Logger *slog.Logger
|
||||
DB *gorm.DB
|
||||
Logger *slog.Logger
|
||||
DB *gorm.DB
|
||||
ActiveSessions []Session
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
Token string
|
||||
UserID uint
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
@ -3,11 +3,12 @@ package utils
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"git.kocoder.xyz/kocoded/vt/model"
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
||||
@ -30,10 +31,10 @@ func setCallbackCookieExp(w http.ResponseWriter, r *http.Request, name, value st
|
||||
http.SetCookie(w, c)
|
||||
}
|
||||
|
||||
func CreateOIDCClient(ctx context.Context, app *fiber.App, logger *slog.Logger) {
|
||||
func CreateOIDCClient(ctx context.Context, app *fiber.App, appCtx Application) {
|
||||
provider, err := oidc.NewProvider(ctx, "https://keycloak.kocoder.xyz/realms/che")
|
||||
if err != nil {
|
||||
logger.Error("Error generating OIDC Provider. ", "error", err)
|
||||
appCtx.Logger.Error("Error generating OIDC Provider. ", "error", err)
|
||||
}
|
||||
|
||||
oauthConfig := oauth2.Config{
|
||||
@ -49,7 +50,7 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, logger *slog.Logger)
|
||||
app.Get("/api/auth", adaptor.HTTPHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
state, err := RandString(16)
|
||||
if err != nil {
|
||||
logger.Warn("Unable to create a state", "error", err)
|
||||
appCtx.Logger.Warn("Unable to create a state", "error", err)
|
||||
http.Error(w, "Unable to create a state", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@ -61,27 +62,27 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, logger *slog.Logger)
|
||||
app.Get("/api/auth/callback", adaptor.HTTPHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
state, err := r.Cookie("state")
|
||||
if err != nil {
|
||||
logger.Warn("State cookie not found", "error", err)
|
||||
appCtx.Logger.Warn("State cookie not found", "error", err)
|
||||
http.Error(w, "state not found", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if r.URL.Query().Get("state") != state.Value {
|
||||
logger.Warn("State cookie and header not matching", "error", err)
|
||||
appCtx.Logger.Warn("State cookie and header not matching", "error", err)
|
||||
http.Error(w, "states not matching", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := oauthConfig.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
logger.Warn("Failed to exchange token", "error", err)
|
||||
appCtx.Logger.Warn("Failed to exchange token", "error", err)
|
||||
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(oauth2Token))
|
||||
if err != nil {
|
||||
logger.Warn("failed to get userinfo", "error", err)
|
||||
appCtx.Logger.Warn("failed to get userinfo", "error", err)
|
||||
http.Error(w, "Failed to get userinfo: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -93,16 +94,47 @@ func CreateOIDCClient(ctx context.Context, app *fiber.App, logger *slog.Logger)
|
||||
|
||||
data, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
logger.Warn("Failed to parse JSON", "error", err)
|
||||
appCtx.Logger.Warn("Failed to parse JSON", "error", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
user := &model.User{}
|
||||
if appCtx.DB.Where(model.User{Email: resp.UserInfo.Email}).Assign(model.User{Sub: resp.UserInfo.Subject}).FirstOrCreate(user).Error != nil {
|
||||
appCtx.Logger.Warn("Failed to create user in DB")
|
||||
http.Error(w, "failed to create user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
setCallbackCookieExp(w, r, "state", "", -1)
|
||||
|
||||
cookie, err := RandString(24)
|
||||
if err != nil {
|
||||
appCtx.Logger.Warn("Couldn't generate session-cookie.")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
setCallbackCookieExp(w, r, "auth-cookie", cookie, int(time.Hour.Seconds()))
|
||||
appCtx.ActiveSessions = append(appCtx.ActiveSessions, Session{Token: cookie, UserID: user.ID, CreatedAt: time.Now()})
|
||||
|
||||
http.Redirect(w, r, "http://localhost:3001", http.StatusFound)
|
||||
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
logger.Error("Unable to send response", "error", err)
|
||||
appCtx.Logger.Error("Unable to send response", "error", err)
|
||||
}
|
||||
}))
|
||||
|
||||
app.Get("/api/auth/currentSession", func(c *fiber.Ctx) error {
|
||||
authToken := c.Cookies("auth-cookie")
|
||||
|
||||
sessionId := slices.IndexFunc(appCtx.ActiveSessions, func(s Session) bool {
|
||||
return s.Token == authToken
|
||||
})
|
||||
|
||||
session := appCtx.ActiveSessions[sessionId]
|
||||
|
||||
return c.JSON(session)
|
||||
})
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ 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.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{})
|
||||
err = db.AutoMigrate(&model.Mandant{}, &model.User{}, &model.Ansprechpartner{}, &model.FirmaAnsprechpartner{}, &model.Firma{})
|
||||
if err != nil {
|
||||
logger.Error("Error setting up Join Tables", "error", err)
|
||||
}
|
||||
@ -38,7 +38,7 @@ func SetupDatabase(dsn string, logger *slog.Logger) *gorm.DB {
|
||||
g.UseDB(db) // reuse your gorm db
|
||||
|
||||
// Generate basic type-safe DAO API for struct `model.User` following conventions
|
||||
g.ApplyBasic(model.Ansprechpartner{}, model.Dokument{}, model.Firma{}, model.Kalender{}, model.Kalendereintrag{}, model.Kostenstelle{}, model.Lager{}, model.Lagerplatz{}, model.Material{}, model.Nachricht{}, model.Projekt{}, model.Rechnung{}, model.Rechnungsposition{}, model.Scanobject{}, model.User{}, model.Zahlung{}, model.FirmaAnsprechpartner{})
|
||||
g.ApplyBasic(model.Mandant{}, model.User{}, model.Ansprechpartner{}, model.Dokument{}, model.Firma{}, model.Kalender{}, model.Kalendereintrag{}, model.Kostenstelle{}, model.Lager{}, model.Lagerplatz{}, model.Material{}, model.Nachricht{}, model.Projekt{}, model.Rechnung{}, model.Rechnungsposition{}, model.Scanobject{}, model.User{}, model.Zahlung{}, model.FirmaAnsprechpartner{})
|
||||
|
||||
// Generate the code
|
||||
g.Execute()
|
||||
|
||||
@ -18,7 +18,10 @@ func RegisterMiddlewares(app *fiber.App) {
|
||||
app.Use(requestid.New())
|
||||
app.Use(compress.New())
|
||||
app.Use(helmet.New())
|
||||
app.Use(cors.New())
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowOrigins: "http://localhost:3000, http://localhost:3001",
|
||||
AllowCredentials: true,
|
||||
}))
|
||||
// app.Use(csrf.New())
|
||||
// app.Use(healthcheck.New(healthcheck.Config{}))
|
||||
app.Use(idempotency.New())
|
||||
|
||||
Reference in New Issue
Block a user