package handlers import ( "context" "errors" "net/http" "strings" "time" "git.jamestombleson.com/jtom38/newsbot-portal/internal/config" "git.jamestombleson.com/jtom38/newsbot-portal/internal/domain" "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" "github.com/a-h/templ" "github.com/golang-jwt/jwt/v5" "github.com/labstack/echo/v4" ) func SetCookie(c echo.Context, key, value, path string) { cookie := new(http.Cookie) cookie.Name = key cookie.Value = value if path != "" { cookie.Path = path } c.SetCookie(cookie) } type jwtToken struct { Exp time.Time `json:"exp"` Iss string `json:"iss"` Authorized bool `json:"authorized"` UserName string `json:"username"` UserId int64 `json:"userId"` Scopes []string `json:"scopes"` SessionToken string `json:"sessionToken"` jwt.RegisteredClaims } func IsLoggedIn(ctx echo.Context) error { _, err := GetUserInfo(ctx) if err != nil { return err } return nil } func HasValidScope(ctx echo.Context, scope string) error { token, err := GetUserInfo(ctx) if err != nil { return err } userScopes := strings.Join(token.Scopes, ",") if strings.Contains(userScopes, scope) { return nil } return errors.New("required permission is missing") } func GetUserInfo(ctx echo.Context) (jwtToken, error) { cfg := config.New() cookie, err := ctx.Cookie(domain.CookieToken) if err != nil { return jwtToken{}, err } if cookie.Value == "" { return jwtToken{}, errors.New("JWT Bearer Token is missing") } token, err := jwt.ParseWithClaims(cookie.Value, &jwtToken{}, func(token *jwt.Token) (interface{}, error) { return []byte(cfg.JwtSecret), nil }) if err != nil { return jwtToken{}, err } if !token.Valid { return jwtToken{}, errors.New("invalid jwt token") } claims := token.Claims.(*jwtToken) if !claims.Exp.After(time.Now()) { return jwtToken{}, errors.New("the jwt token has expired") } return *claims, nil } func GetJwtToken(c echo.Context) string { cookie, err := c.Cookie(domain.CookieToken) if err != nil { return "" } return cookie.Value } func Render(ctx echo.Context, statusCode int, t templ.Component) error { ctx.Response().Writer.WriteHeader(statusCode) ctx.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML) // take the request context and make it a var request := ctx.Request().Context() //Check to see if we the echo context has the cookie we are looking for, if so, create a new context based on what we had and add the value username, err := ctx.Cookie(domain.CookieUser) if err == nil { request = context.WithValue(request, domain.UserNameContext, username.Value) } else { request = context.WithValue(request, domain.UserNameContext, "") } return t.Render(request, ctx.Response().Writer) } func RenderError(ctx echo.Context, err error) error { var t templ.Component = layout.Error(err) ctx.Response().Writer.WriteHeader(200) ctx.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML) // take the request context and make it a var request := ctx.Request().Context() //Check to see if we the echo context has the cookie we are looking for, if so, create a new context based on what we had and add the value username, err := ctx.Cookie(domain.CookieUser) if err == nil { request = context.WithValue(request, domain.UserNameContext, username.Value) } else { request = context.WithValue(request, domain.UserNameContext, "") } return t.Render(request, ctx.Response().Writer) }