opengist/internal/web/server/middlewares.go

176 lines
4.6 KiB
Go
Raw Normal View History

2024-12-03 01:18:04 +00:00
package server
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/i18n"
"github.com/thomiceli/opengist/internal/web/context"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"net/http"
"strings"
"time"
)
func (s *Server) useCustomContext() {
s.echo.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cc := context.NewContext(c)
return next(cc)
}
})
}
func (s *Server) RegisterMiddlewares(e *echo.Echo) {
e.Use(Middleware(dataInit).ToEcho())
e.Use(Middleware(locale).ToEcho())
e.Pre(middleware.MethodOverrideWithConfig(middleware.MethodOverrideConfig{
Getter: middleware.MethodFromForm("_method"),
}))
e.Pre(middleware.RemoveTrailingSlash())
e.Pre(middleware.CORS())
e.Pre(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
LogURI: true, LogStatus: true, LogMethod: true,
LogValuesFunc: func(ctx echo.Context, v middleware.RequestLoggerValues) error {
log.Info().Str("uri", v.URI).Int("status", v.Status).Str("method", v.Method).
Str("ip", ctx.RealIP()).TimeDiff("duration", time.Now(), v.StartTime).
Msg("HTTP")
return nil
},
}))
e.Use(middleware.Recover())
e.Use(middleware.Secure())
e.Use(Middleware(sessionInit).ToEcho())
}
func dataInit(next Handler) Handler {
return func(ctx *context.OGContext) error {
ctx.SetData("loadStartTime", time.Now())
if err := loadSettings(ctx); err != nil {
return ctx.ErrorRes(500, "Cannot load settings", err)
}
ctx.SetData("c", config.C)
ctx.SetData("githubOauth", config.C.GithubClientKey != "" && config.C.GithubSecret != "")
ctx.SetData("gitlabOauth", config.C.GitlabClientKey != "" && config.C.GitlabSecret != "")
ctx.SetData("giteaOauth", config.C.GiteaClientKey != "" && config.C.GiteaSecret != "")
ctx.SetData("oidcOauth", config.C.OIDCClientKey != "" && config.C.OIDCSecret != "" && config.C.OIDCDiscoveryUrl != "")
httpProtocol := "http"
if ctx.Request().TLS != nil || ctx.Request().Header.Get("X-Forwarded-Proto") == "https" {
httpProtocol = "https"
}
ctx.SetData("httpProtocol", strings.ToUpper(httpProtocol))
var baseHttpUrl string
// if a custom external url is set, use it
if config.C.ExternalUrl != "" {
baseHttpUrl = config.C.ExternalUrl
} else {
baseHttpUrl = httpProtocol + "://" + ctx.Request().Host
}
ctx.SetData("baseHttpUrl", baseHttpUrl)
return next(ctx)
}
}
func locale(next Handler) Handler {
return func(ctx *context.OGContext) error {
// Check URL arguments
lang := ctx.Request().URL.Query().Get("lang")
changeLang := lang != ""
// Then check cookies
if len(lang) == 0 {
cookie, _ := ctx.Request().Cookie("lang")
if cookie != nil {
lang = cookie.Value
}
}
// Check again in case someone changes the supported language list.
if lang != "" && !i18n.Locales.HasLocale(lang) {
lang = ""
changeLang = false
}
// 3.Then check from 'Accept-Language' header.
if len(lang) == 0 {
tags, _, _ := language.ParseAcceptLanguage(ctx.Request().Header.Get("Accept-Language"))
lang = i18n.Locales.MatchTag(tags)
}
if changeLang {
ctx.SetCookie(&http.Cookie{Name: "lang", Value: lang, Path: "/", MaxAge: 1<<31 - 1})
}
localeUsed, err := i18n.Locales.GetLocale(lang)
if err != nil {
return ctx.ErrorRes(500, "Cannot get locale", err)
}
ctx.SetData("localeName", localeUsed.Name)
ctx.SetData("locale", localeUsed)
ctx.SetData("allLocales", i18n.Locales.Locales)
return next(ctx)
}
}
func sessionInit(next Handler) Handler {
return func(ctx *context.OGContext) error {
sess := ctx.GetSession()
if sess.Values["user"] != nil {
var err error
var user *db.User
if user, err = db.GetUserById(sess.Values["user"].(uint)); err != nil {
sess.Values["user"] = nil
ctx.SaveSession(sess)
ctx.User = nil
ctx.SetData("userLogged", nil)
return ctx.RedirectTo("/all")
}
if user != nil {
ctx.User = user
ctx.SetData("userLogged", user)
}
return next(ctx)
}
ctx.User = nil
ctx.SetData("userLogged", nil)
return next(ctx)
}
}
func csrfInit(next Handler) Handler {
return func(ctx *context.OGContext) error {
setCsrfHtmlForm(ctx)
return next(ctx)
}
}
func loadSettings(ctx *context.OGContext) error {
settings, err := db.GetSettings()
if err != nil {
return err
}
for key, value := range settings {
s := strings.ReplaceAll(key, "-", " ")
s = cases.Title(language.English).String(s)
ctx.SetData(strings.ReplaceAll(s, " ", ""), value == "1")
}
return nil
}