Add auth
This commit is contained in:
parent
34486a6ca4
commit
00915c67d7
12 changed files with 152 additions and 77 deletions
|
@ -1,8 +1,6 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import "gitlab.unjx.de/flohoss/godash/services"
|
||||||
"gitlab.unjx.de/flohoss/godash/services"
|
|
||||||
)
|
|
||||||
|
|
||||||
templ Application(application services.Application) {
|
templ Application(application services.Application) {
|
||||||
<a href={ templ.URL(application.URL) } class="flex items-center hover-effect">
|
<a href={ templ.URL(application.URL) } class="flex items-center hover-effect">
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
|
||||||
"gitlab.unjx.de/flohoss/godash/services"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gitlab.unjx.de/flohoss/godash/services"
|
||||||
|
"html/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
var BarTemplate = template.Must(template.New("bar").Parse("<div id=\"{{ .Id }}\" class=\"progress-bar\" style=\"width: {{ .Percentage }}%\"></div>"))
|
var BarTemplate = template.Must(template.New("bar").Parse("<div id=\"{{ .Id }}\" class=\"progress-bar\" style=\"width: {{ .Percentage }}%\"></div>"))
|
||||||
|
@ -20,7 +20,7 @@ templ System(icon string, infoPre string, infoPost string, extraInfo string, per
|
||||||
<div class="extra-info">{ extraInfo }</div>
|
<div class="extra-info">{ extraInfo }</div>
|
||||||
<div class="truncate"><span id={ valueId }>{ infoPre }</span>{ infoPost }</div>
|
<div class="truncate"><span id={ valueId }>{ infoPre }</span>{ infoPost }</div>
|
||||||
<div class="progress-bar-wrapper">
|
<div class="progress-bar-wrapper">
|
||||||
@templ.FromGoHTML(BarTemplate, Bar{Id:percentageId, Percentage:percentage})
|
@templ.FromGoHTML(BarTemplate, Bar{Id: percentageId, Percentage: percentage})
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,18 +42,18 @@ templ Uptime(extraInfo string, id string, uptime services.Uptime) {
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
<span><span id="uptimeDays">{ fmt.Sprintf("%d",uptime.Days) }</span> days</span>
|
<span><span id="uptimeDays">{ fmt.Sprintf("%d",uptime.Days) }</span> days</span>
|
||||||
<span class="countdown">
|
<span class="countdown">
|
||||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeHours", Value:uptime.Hours})
|
@templ.FromGoHTML(countDownTemplate, Countdown{Id: "uptimeHours", Value: uptime.Hours})
|
||||||
</span> hours
|
</span> hours
|
||||||
<span class="countdown">
|
<span class="countdown">
|
||||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeMinutes", Value:uptime.Minutes})
|
@templ.FromGoHTML(countDownTemplate, Countdown{Id: "uptimeMinutes", Value: uptime.Minutes})
|
||||||
</span> min
|
</span> min
|
||||||
<span class="countdown">
|
<span class="countdown">
|
||||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeSeconds", Value:uptime.Seconds})
|
@templ.FromGoHTML(countDownTemplate, Countdown{Id: "uptimeSeconds", Value: uptime.Seconds})
|
||||||
</span> sec
|
</span> sec
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-bar-wrapper">
|
<div class="progress-bar-wrapper">
|
||||||
@templ.FromGoHTML(BarTemplate, Bar{Id:id, Percentage:float64(uptime.Percentage)})
|
@templ.FromGoHTML(BarTemplate, Bar{Id: id, Percentage: float64(uptime.Percentage)})
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
11
components/user.templ
Normal file
11
components/user.templ
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
import "gitlab.unjx.de/flohoss/godash/services"
|
||||||
|
|
||||||
|
templ User(user services.User) {
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="ring-primary ring-offset-base-100 w-16 rounded-full ring-2 ring-offset-2">
|
||||||
|
<img src={ string(templ.SafeURL(user.Gravatar)) }/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gitlab.unjx.de/flohoss/godash/services"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gitlab.unjx.de/flohoss/godash/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getIcon(icon string) string {
|
func getIcon(icon string) string {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,11 +4,13 @@ go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/a-h/templ v0.2.778
|
github.com/a-h/templ v0.2.778
|
||||||
|
github.com/alexedwards/scs/v2 v2.8.0
|
||||||
github.com/caarlos0/env/v10 v10.0.0
|
github.com/caarlos0/env/v10 v10.0.0
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0
|
github.com/coreos/go-oidc/v3 v3.11.0
|
||||||
github.com/go-playground/validator/v10 v10.22.1
|
github.com/go-playground/validator/v10 v10.22.1
|
||||||
github.com/r3labs/sse/v2 v2.10.0
|
github.com/r3labs/sse/v2 v2.10.0
|
||||||
github.com/shirou/gopsutil/v4 v4.24.8
|
github.com/shirou/gopsutil/v4 v4.24.8
|
||||||
|
github.com/thanhpk/randstr v1.0.6
|
||||||
golang.org/x/oauth2 v0.23.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,5 +1,7 @@
|
||||||
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
|
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
|
||||||
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
|
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
|
||||||
|
github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
|
||||||
|
github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
|
||||||
github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA=
|
github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA=
|
||||||
github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18=
|
github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18=
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
||||||
|
@ -56,6 +58,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o=
|
||||||
|
github.com/thanhpk/randstr v1.0.6/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
|
||||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||||
|
|
|
@ -38,10 +38,6 @@ type AppHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bh *AppHandler) appHandler(w http.ResponseWriter, r *http.Request) {
|
func (bh *AppHandler) appHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Redirect(w, r, "/", http.StatusFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
bookmarks := bh.bookmarkService.GetAllBookmarks()
|
bookmarks := bh.bookmarkService.GetAllBookmarks()
|
||||||
staticSystem := bh.systemService.GetStaticInformation()
|
staticSystem := bh.systemService.GetStaticInformation()
|
||||||
liveSystem := bh.systemService.GetLiveInformation()
|
liveSystem := bh.systemService.GetLiveInformation()
|
||||||
|
@ -49,5 +45,12 @@ func (bh *AppHandler) appHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
titlePage := bh.env.Title
|
titlePage := bh.env.Title
|
||||||
|
|
||||||
home.HomeIndex(titlePage, bh.env.Version, home.Home(titlePage, bookmarks, staticSystem, liveSystem, weather)).Render(r.Context(), w)
|
user := services.User{
|
||||||
|
Name: w.Header().Get("X-User-Name"),
|
||||||
|
Email: w.Header().Get("X-User-Email"),
|
||||||
|
}
|
||||||
|
gravatar := services.NewGravatarFromEmail(user.Email)
|
||||||
|
user.Gravatar = gravatar.GetURL()
|
||||||
|
|
||||||
|
home.HomeIndex(titlePage, bh.env.Version, home.Home(titlePage, user, bookmarks, staticSystem, liveSystem, weather)).Render(r.Context(), w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,21 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/alexedwards/scs/v2"
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
|
"github.com/thanhpk/randstr"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"gitlab.unjx.de/flohoss/godash/internal/env"
|
"gitlab.unjx.de/flohoss/godash/internal/env"
|
||||||
|
"gitlab.unjx.de/flohoss/godash/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randString(nByte int) (string, error) {
|
|
||||||
b := make([]byte, nByte)
|
|
||||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return base64.RawURLEncoding.EncodeToString(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) {
|
func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) {
|
||||||
c := &http.Cookie{
|
c := &http.Cookie{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -80,15 +73,21 @@ func NewAuthHandler(env *env.Config) *AuthHandler {
|
||||||
}
|
}
|
||||||
codeChallenge := generateCodeChallenge(codeVerifier)
|
codeChallenge := generateCodeChallenge(codeVerifier)
|
||||||
authCodeOptions := []oauth2.AuthCodeOption{
|
authCodeOptions := []oauth2.AuthCodeOption{
|
||||||
|
oauth2.SetAuthURLParam("redirect_uri", env.OIDCRedirectURI),
|
||||||
oauth2.SetAuthURLParam("code_challenge", codeChallenge),
|
oauth2.SetAuthURLParam("code_challenge", codeChallenge),
|
||||||
oauth2.SetAuthURLParam("code_challenge_method", "S256"),
|
oauth2.SetAuthURLParam("code_challenge_method", "S256"),
|
||||||
|
oauth2.SetAuthURLParam("code_verifier", codeVerifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionManager := scs.New()
|
||||||
|
sessionManager.Lifetime = 24 * time.Hour
|
||||||
|
|
||||||
return &AuthHandler{
|
return &AuthHandler{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
oidcProvider: oidcProvider,
|
oidcProvider: oidcProvider,
|
||||||
oauth2Config: oauth2Config,
|
oauth2Config: oauth2Config,
|
||||||
authCodeOptions: authCodeOptions,
|
authCodeOptions: authCodeOptions,
|
||||||
|
SessionManager: sessionManager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,17 +96,7 @@ type AuthHandler struct {
|
||||||
oidcProvider *oidc.Provider
|
oidcProvider *oidc.Provider
|
||||||
oauth2Config *oauth2.Config
|
oauth2Config *oauth2.Config
|
||||||
authCodeOptions []oauth2.AuthCodeOption
|
authCodeOptions []oauth2.AuthCodeOption
|
||||||
}
|
SessionManager *scs.SessionManager
|
||||||
|
|
||||||
func (ah *AuthHandler) handleAuth(w http.ResponseWriter, r *http.Request) {
|
|
||||||
state, err := randString(16)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Internal error", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setCallbackCookie(w, r, "state", state)
|
|
||||||
|
|
||||||
http.Redirect(w, r, ah.oauth2Config.AuthCodeURL(state, ah.authCodeOptions...), http.StatusFound)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *AuthHandler) handleCallback(w http.ResponseWriter, r *http.Request) {
|
func (ah *AuthHandler) handleCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -121,49 +110,46 @@ func (ah *AuthHandler) handleCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oauth2Token, err := ah.oauth2Config.Exchange(ah.ctx, r.URL.Query().Get("code"))
|
oauth2Token, err := ah.oauth2Config.Exchange(ah.ctx, r.URL.Query().Get("code"), ah.authCodeOptions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo, err := ah.oidcProvider.UserInfo(ah.ctx, oauth2.StaticTokenSource(oauth2Token))
|
ah.SessionManager.Put(r.Context(), "access_token", oauth2Token.AccessToken)
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "failed to get userinfo: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := struct {
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
OAuth2Token *oauth2.Token
|
}
|
||||||
UserInfo *oidc.UserInfo
|
|
||||||
}{oauth2Token, userInfo}
|
func (ah *AuthHandler) handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := json.MarshalIndent(resp, "", " ")
|
ah.SessionManager.Clear(r.Context())
|
||||||
if err != nil {
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
}
|
||||||
return
|
|
||||||
}
|
func (ah *AuthHandler) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write(data)
|
state := randstr.String(16)
|
||||||
|
setCallbackCookie(w, r, "state", state)
|
||||||
|
http.Redirect(w, r, ah.oauth2Config.AuthCodeURL(state, ah.authCodeOptions...), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ah *AuthHandler) AuthMiddleware(next http.Handler) http.Handler {
|
func (ah *AuthHandler) AuthMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
state, err := r.Cookie("state")
|
accessToken := ah.SessionManager.GetString(r.Context(), "access_token")
|
||||||
if err != nil {
|
if accessToken == "" {
|
||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
ah.handleLogin(w, r)
|
||||||
return
|
|
||||||
}
|
|
||||||
oauth2Token, err := ah.oauth2Config.Exchange(ah.ctx, r.URL.Query().Get("code"))
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo, err := ah.oidcProvider.UserInfo(ah.ctx, oauth2.StaticTokenSource(oauth2Token))
|
userInfo, err := ah.oidcProvider.UserInfo(ah.ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
ah.handleLogin(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(userInfo)
|
var userClaims services.User
|
||||||
|
userInfo.Claims(&userClaims)
|
||||||
|
w.Header().Set("X-User-Name", userClaims.Name)
|
||||||
|
w.Header().Set("X-User-Email", userClaims.Email)
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(router *http.ServeMux, sse *sse.Server, appHandler *AppHandler, authHandler *AuthHandler) {
|
func SetupRoutes(router *http.ServeMux, sse *sse.Server, appHandler *AppHandler, authHandler *AuthHandler) {
|
||||||
router.HandleFunc("GET /sse", sse.ServeHTTP)
|
router.Handle("GET /sse", authHandler.AuthMiddleware(http.HandlerFunc(sse.ServeHTTP)))
|
||||||
|
|
||||||
fsAssets := http.FileServer(http.Dir("assets"))
|
fsAssets := http.FileServer(http.Dir("assets"))
|
||||||
router.Handle("GET /assets/", http.StripPrefix("/assets/", fsAssets))
|
router.Handle("GET /assets/", authHandler.AuthMiddleware((http.StripPrefix("/assets/", fsAssets))))
|
||||||
|
|
||||||
icons := http.FileServer(http.Dir("storage/icons"))
|
icons := http.FileServer(http.Dir("storage/icons"))
|
||||||
router.Handle("GET /icons/", http.StripPrefix("/icons/", icons))
|
router.Handle("GET /icons/", authHandler.AuthMiddleware(http.StripPrefix("/icons/", icons)))
|
||||||
|
|
||||||
router.HandleFunc("GET /login", authHandler.handleAuth)
|
router.HandleFunc("GET /auth/logout", http.HandlerFunc(authHandler.handleLogout))
|
||||||
router.HandleFunc("GET /auch/callback", authHandler.handleCallback)
|
router.HandleFunc("GET /auth/callback", authHandler.handleCallback)
|
||||||
|
|
||||||
router.Handle("GET /", authHandler.AuthMiddleware(http.HandlerFunc(appHandler.appHandler)))
|
router.Handle("GET /", authHandler.AuthMiddleware(http.HandlerFunc(appHandler.appHandler)))
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -35,7 +35,7 @@ func main() {
|
||||||
|
|
||||||
lis := fmt.Sprintf(":%d", env.Port)
|
lis := fmt.Sprintf(":%d", env.Port)
|
||||||
slog.Info("server listening, press ctrl+c to stop", "addr", "http://localhost"+lis)
|
slog.Info("server listening, press ctrl+c to stop", "addr", "http://localhost"+lis)
|
||||||
err = http.ListenAndServe(lis, router)
|
err = http.ListenAndServe(lis, authHandler.SessionManager.LoadAndSave(router))
|
||||||
if !errors.Is(err, http.ErrServerClosed) {
|
if !errors.Is(err, http.ErrServerClosed) {
|
||||||
slog.Error("server terminated", "error", err)
|
slog.Error("server terminated", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
71
services/claims.services.go
Normal file
71
services/claims.services.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Gravatar string `json:"gravatar"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultScheme = "https"
|
||||||
|
defaultHostname = "www.gravatar.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewGravatarFromEmail(email string) Gravatar {
|
||||||
|
hasher := sha256.Sum256([]byte(strings.TrimSpace(email)))
|
||||||
|
hash := hex.EncodeToString(hasher[:])
|
||||||
|
|
||||||
|
g := NewGravatar()
|
||||||
|
g.Hash = hash
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGravatar() Gravatar {
|
||||||
|
return Gravatar{
|
||||||
|
Scheme: defaultScheme,
|
||||||
|
Host: defaultHostname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Gravatar struct {
|
||||||
|
Scheme string
|
||||||
|
Host string
|
||||||
|
Hash string
|
||||||
|
Default string
|
||||||
|
Rating string
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g Gravatar) GetURL() string {
|
||||||
|
path := "/avatar/" + g.Hash
|
||||||
|
|
||||||
|
v := url.Values{}
|
||||||
|
if g.Size > 0 {
|
||||||
|
v.Add("s", strconv.Itoa(g.Size))
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Rating != "" {
|
||||||
|
v.Add("r", g.Rating)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Default != "" {
|
||||||
|
v.Add("d", g.Default)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := url.URL{
|
||||||
|
Scheme: g.Scheme,
|
||||||
|
Host: g.Host,
|
||||||
|
Path: path,
|
||||||
|
RawQuery: v.Encode(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.String()
|
||||||
|
}
|
|
@ -2,22 +2,22 @@ package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gitlab.unjx.de/flohoss/godash/components"
|
||||||
"gitlab.unjx.de/flohoss/godash/services"
|
"gitlab.unjx.de/flohoss/godash/services"
|
||||||
"gitlab.unjx.de/flohoss/godash/views/layout"
|
"gitlab.unjx.de/flohoss/godash/views/layout"
|
||||||
"gitlab.unjx.de/flohoss/godash/components"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
templ Home(title string, bookmarks *services.Bookmarks, static *services.StaticInformation, live *services.LiveInformation, weather *services.OpenWeather) {
|
templ Home(title string, user services.User, bookmarks *services.Bookmarks, static *services.StaticInformation, live *services.LiveInformation, weather *services.OpenWeather) {
|
||||||
<section class="grid gap-10">
|
<section class="grid gap-10">
|
||||||
<div class="flex w-full justify-between items-center">
|
<div class="flex w-full justify-between items-center">
|
||||||
@components.Weather(weather)
|
@components.Weather(weather)
|
||||||
|
@components.User(user)
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3 select-none">
|
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3 select-none">
|
||||||
@components.System("icon-[bi--cpu]",static.CPU.Name,"",static.CPU.Threads,"systemCpuPercentage","",live.CPU)
|
@components.System("icon-[bi--cpu]", static.CPU.Name, "", static.CPU.Threads, "systemCpuPercentage", "", live.CPU)
|
||||||
@components.System("icon-[bi--nvme]",live.Disk.Value,fmt.Sprintf(" | %s", static.Disk.Total),static.Disk.Partitions,"systemDiskPercentage","systemDiskValue",live.Disk.Percentage)
|
@components.System("icon-[bi--nvme]", live.Disk.Value, fmt.Sprintf(" | %s", static.Disk.Total), static.Disk.Partitions, "systemDiskPercentage", "systemDiskValue", live.Disk.Percentage)
|
||||||
@components.System("icon-[bi--memory]",live.Ram.Value,fmt.Sprintf(" | %s", static.Ram.Total),static.Ram.Swap,"systemRamPercentage","systemRamValue",live.Ram.Percentage)
|
@components.System("icon-[bi--memory]", live.Ram.Value, fmt.Sprintf(" | %s", static.Ram.Total), static.Ram.Swap, "systemRamPercentage", "systemRamValue", live.Ram.Percentage)
|
||||||
@components.Uptime(static.Host.Architecture,"systemUptimePercentage",live.Uptime)
|
@components.Uptime(static.Host.Architecture, "systemUptimePercentage", live.Uptime)
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-4">
|
<div class="grid gap-4">
|
||||||
for _, a := range bookmarks.Applications {
|
for _, a := range bookmarks.Applications {
|
||||||
|
|
Loading…
Reference in a new issue