diff --git a/apiclient/users.go b/apiclient/users.go
index 7510802..37ec219 100644
--- a/apiclient/users.go
+++ b/apiclient/users.go
@@ -15,6 +15,8 @@ const (
type Users interface {
Login(username, password string) (domain.LoginResponse, error)
SignUp(username, password string) (domain.BaseResponse, error)
+ RefreshJwtToken(username, refreshToken string) (domain.LoginResponse, error)
+ RefreshSessionToken(jwtToken string) (domain.BaseResponse, error)
}
type userClient struct {
@@ -79,11 +81,11 @@ func (a userClient) RefreshJwtToken(username, refreshToken string) (domain.Login
return bind, nil
}
-func (a userClient) refreshSessionToken() (domain.BaseResponse, error) {
+func (a userClient) RefreshSessionToken(jwtToken string) (domain.BaseResponse, error) {
endpoint := fmt.Sprintf("%s/%s/refresh/sessionToken", a.serverAddress, UserBaseRoute)
var bind = domain.BaseResponse{}
- err := PostUrl(a.client, endpoint, &bind)
+ err := PostUrlAuthorized(a.client, endpoint, jwtToken, &bind)
if err != nil {
return domain.BaseResponse{}, err
}
diff --git a/apiclient/util.go b/apiclient/util.go
index 441e89e..4c7d212 100644
--- a/apiclient/util.go
+++ b/apiclient/util.go
@@ -3,10 +3,15 @@ package apiclient
import (
"bytes"
"encoding/json"
+ "fmt"
"net/http"
"net/url"
)
+const (
+ HeaderAuthorization = "Authorization"
+)
+
func PostUrlForm(client http.Client, endpoint string, param url.Values, t any) error {
payload := bytes.NewBufferString(param.Encode())
req, err := http.NewRequest(http.MethodPost, endpoint, payload)
@@ -30,8 +35,15 @@ func PostUrlForm(client http.Client, endpoint string, param url.Values, t any) e
return nil
}
-func PostUrl(client http.Client, endpoint string, t any) error {
- response, err := http.Post(endpoint, ApplicationJson, nil)
+func PostUrlAuthorized(client http.Client, endpoint, jwtToken string, t any) error {
+ req, err := http.NewRequest(http.MethodPost, endpoint, nil)
+ if err != nil {
+ return err
+ }
+ req.Header.Add(HeaderAuthorization, fmt.Sprintf("%s %s", "Bearer", jwtToken))
+
+ response, err := client.Do(req)
+ //response, err := http.Post(endpoint, ApplicationJson, nil)
if err != nil {
return err
}
diff --git a/go.mod b/go.mod
index d372940..0dac382 100644
--- a/go.mod
+++ b/go.mod
@@ -5,8 +5,9 @@ go 1.22.1
require (
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240510021003-4e9a17209f02
github.com/a-h/templ v0.2.680
- github.com/golang-jwt/jwt/v4 v4.5.0
+ github.com/golang-jwt/jwt/v5 v5.2.1
github.com/joho/godotenv v1.5.1
+ github.com/labstack/echo-jwt/v4 v4.2.0
github.com/labstack/echo/v4 v4.12.0
)
diff --git a/go.sum b/go.sum
index 7666828..dc0ffa7 100644
--- a/go.sum
+++ b/go.sum
@@ -6,12 +6,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
-github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
+github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c=
+github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
diff --git a/internal/handlers/handler.go b/internal/handlers/handler.go
index 946979a..26f6c8c 100644
--- a/internal/handlers/handler.go
+++ b/internal/handlers/handler.go
@@ -44,17 +44,11 @@ func NewServer(ctx context.Context, configs config.Configs, apiClient apiclient.
api: apiClient,
}
- //jwtConfig := echojwt.Config{
- // NewClaimsFunc: func(c echo.Context) jwt.Claims {
- // return new(JwtToken)
- // },
- // SigningKey: []byte(configs.JwtSecret),
- //}
-
router := echo.New()
router.Pre(middleware.RemoveTrailingSlash())
router.Pre(middleware.Logger())
router.Pre(middleware.Recover())
+ router.Use(middleware.Static("/internal/static"))
router.GET("/", s.HomeIndex)
router.GET("/about", s.HomeAbout)
@@ -71,6 +65,9 @@ func NewServer(ctx context.Context, configs config.Configs, apiClient apiclient.
users.GET("/signup", s.UserSignUp)
users.POST("/signup", s.UserAfterSignUp)
+ //users.Use(echojwt.WithConfig(jwtConfig))
+ users.GET("/profile", s.UserProfile)
+
s.Router = router
return s
}
diff --git a/internal/handlers/users.go b/internal/handlers/users.go
index 2571e27..b12bebb 100644
--- a/internal/handlers/users.go
+++ b/internal/handlers/users.go
@@ -5,6 +5,7 @@ import (
"net/http"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/domain"
+ "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/users"
"github.com/labstack/echo/v4"
)
@@ -46,4 +47,18 @@ func (h *Handler) UserAfterSignUp(c echo.Context) error {
return Render(c, http.StatusBadRequest, users.AfterLogin(msg, false))
}
return Render(c, http.StatusOK, users.AfterSignUp("Registration Successful!", true))
-}
\ No newline at end of file
+}
+
+func (h *Handler) UserProfile(c echo.Context) error {
+ return Render(c, http.StatusOK, users.Profile())
+}
+
+func (h *Handler) ForceLogout(c echo.Context) error {
+ _, err := ValidateJwt(c, h.config.JwtSecret, h.config.ServerAddress)
+ if err != nil {
+ return Render(c, http.StatusOK, layout.Error(err))
+ }
+
+ h.api.Users.RefreshSessionToken(GetJwtToken(c))
+ return nil
+}
diff --git a/internal/handlers/util.go b/internal/handlers/util.go
index 91a8aff..0eaea40 100644
--- a/internal/handlers/util.go
+++ b/internal/handlers/util.go
@@ -8,7 +8,7 @@ import (
"git.jamestombleson.com/jtom38/newsbot-portal/internal/domain"
"github.com/a-h/templ"
- "github.com/golang-jwt/jwt/v4"
+ "github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
)
@@ -23,11 +23,13 @@ func SetCookie(c echo.Context, key, value, path string) {
}
type jwtToken struct {
- Exp time.Time `json:"exp"`
- Iss string `json:"iss"`
- Authorized bool `json:"authorized"`
- UserName string `json:"username"`
- Scopes []string `json:"scopes"`
+ 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
}
@@ -63,6 +65,14 @@ func ValidateJwt(ctx echo.Context, sharedSecret, issuer string) (jwtToken, error
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)
diff --git a/internal/views/bulma/hero.templ b/internal/views/bulma/hero.templ
new file mode 100644
index 0000000..ce5dd39
--- /dev/null
+++ b/internal/views/bulma/hero.templ
@@ -0,0 +1,10 @@
+package bulma
+
+templ Hero(title, subtitle string) {
+ { title } { subtitle }Section
+
+ A simple container to divide your page into sections, like
+ the one you're currently reading.
+
+
diff --git a/internal/views/layout/footer.templ b/internal/views/layout/footer.templ index 167ff62..d8d8e8c 100644 --- a/internal/views/layout/footer.templ +++ b/internal/views/layout/footer.templ @@ -1,15 +1,7 @@ package layout templ footer() { - -} \ No newline at end of file +
This will force all active sessions to stop working and require a new login.
+ } +}