Skip to content

Commit

Permalink
add login/logout logic and session handling
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrosius committed Dec 26, 2024
1 parent 4467e69 commit 6092786
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 38 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/gin-gonic/gin v1.10.0
github.com/spf13/viper v1.19.0
software.sslmate.com/src/go-pkcs12 v0.5.0
github.com/gorilla/sessions v1.4.0
)

require (
Expand All @@ -20,6 +21,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/goccy/go-json v0.10.4 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PU
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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
Expand Down
97 changes: 72 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ import (
"time"

"github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
"github.com/spf13/viper"
)

// create variable for session handling (login/logout)
var store = sessions.NewCookieStore([]byte("secret-key"))

// toJson converts a Go data structure to a JSON string
func toJson(v interface{}) (string, error) {
bytes, err := json.Marshal(v)
Expand Down Expand Up @@ -163,34 +167,41 @@ func main() {
// Load templates with the function map
r.LoadHTMLGlob("templates/*")

r.GET("/", showHomePage)
r.GET("/certificates", checkRootCertAndListCerts) // Ensure this route calls the correct function
r.GET("/certificates/view/:filename", viewCertificate)
r.POST("/certificates/delete/:filename", deleteCertificate)
r.GET("/certificates/download/:filename", func(c *gin.Context) {
c.Params = append(c.Params, gin.Param{Key: "certType", Value: "certs"})
downloadCertificate(c)
})
r.POST("/create-root-certificate", createRootCertificate)
r.GET("/certificates/download/root-cert/:filename", func(c *gin.Context) {
c.Params = append(c.Params, gin.Param{Key: "certType", Value: "root-cert"})
downloadCertificate(c)
})
r.GET("/create-certificate-form", showCreateCertificateForm) // Route for certificate form
r.POST("/create-certificate", createCertificate)

r.POST("/certificates/delete/root-cert/:filename", deleteRootCertificate) // Route for deleting root certificate
r.GET("/settings", showSettingsPage) // Route for settings page
// r.POST("/settings", handleSettings) // Route for saving settings
r.GET("/howto", showHowToPage) // Add this new route
r.POST("/recreate-homelab-cert", recreateHomelabCertificate)
r.GET("/login", showLoginPage)
r.POST("/login", handleLogin)
r.GET("/logout", handleLogout)

authorized := r.Group("/")
authorized.Use(AuthRequired)
{
authorized.GET("/", showHomePage)
authorized.GET("/certificates", checkRootCertAndListCerts) // Ensure this route calls the correct function
authorized.GET("/certificates/view/:filename", viewCertificate)
authorized.POST("/certificates/delete/:filename", deleteCertificate)
authorized.GET("/certificates/download/:filename", func(c *gin.Context) {
c.Params = append(c.Params, gin.Param{Key: "certType", Value: "certs"})
downloadCertificate(c)
})
authorized.POST("/create-root-certificate", createRootCertificate)
authorized.GET("/certificates/download/root-cert/:filename", func(c *gin.Context) {
c.Params = append(c.Params, gin.Param{Key: "certType", Value: "root-cert"})
downloadCertificate(c)
})
authorized.GET("/create-certificate-form", showCreateCertificateForm) // Route for certificate form
authorized.POST("/create-certificate", createCertificate)

r.GET("/settings/certmanager", handleCertManagerSettings)
r.POST("/settings/certmanager", handleCertManagerSettings)
authorized.POST("/certificates/delete/root-cert/:filename", deleteRootCertificate) // Route for deleting root certificate
authorized.GET("/settings", showSettingsPage) // Route for settings page
// r.POST("/settings", handleSettings) // Route for saving settings
authorized.GET("/howto", showHowToPage) // Add this new route
authorized.POST("/recreate-homelab-cert", recreateHomelabCertificate)

r.GET("/settings/generalcertoptions", handleGeneralCertOptions)
r.POST("/settings/generalcertoptions", handleGeneralCertOptions)
authorized.GET("/settings/certmanager", handleCertManagerSettings)
authorized.POST("/settings/certmanager", handleCertManagerSettings)

authorized.GET("/settings/generalcertoptions", handleGeneralCertOptions)
authorized.POST("/settings/generalcertoptions", handleGeneralCertOptions)
}
// Determine which certificate to use
selfSignedCert := filepath.Join("data", "certmanager-cert", "selfsigned.pem")
selfSignedKey := filepath.Join("data", "certmanager-cert", "selfsigned.key")
Expand Down Expand Up @@ -385,3 +396,39 @@ func renderTemplate(c *gin.Context, templateName string, data gin.H) {
}
c.HTML(http.StatusOK, templateName, data)
}

func showLoginPage(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", nil)
}

func handleLogin(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")

// Replace with your own authentication logic
if username == "admin" && password == "password" {
session, _ := store.Get(c.Request, "session")
session.Values["authenticated"] = true
session.Save(c.Request, c.Writer)
c.Redirect(http.StatusSeeOther, "/certificates")
} else {
c.HTML(http.StatusUnauthorized, "login.html", gin.H{"error": "Invalid credentials"})
}
}

func handleLogout(c *gin.Context) {
session, _ := store.Get(c.Request, "session")
session.Values["authenticated"] = false
session.Save(c.Request, c.Writer)
c.Redirect(http.StatusSeeOther, "/login")
}

func AuthRequired(c *gin.Context) {
session, _ := store.Get(c.Request, "session")
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
c.Redirect(http.StatusSeeOther, "/login")
c.Abort()
return
}
c.Next()
}
50 changes: 37 additions & 13 deletions templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,42 @@
<!-- Custom CSS -->
<link rel="stylesheet" href="/static/styles.css">
<script>
// Initialize theme before page load
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('theme', theme);
// document.body.setAttribute('theme', theme);
</script>
<style>
.nowrap-title {
white-space: nowrap;
}
.login-card {
background: rgba(255, 255, 255, 0.9);
padding: 20px;
border-radius: 8px;
}
.card-content {
background: url('/static/Homelab Certification Authority.png') no-repeat center center;
background-size: cover;
padding: 50px;
border-radius: 20px;
}
.center-button {
display: flex;
justify-content: center;
}
.input-field {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="container">
<div class="row" style="margin-top: 100px;">
<div class="center-align">
<h2 class="nowrap-title">HomeLAB Certificate Manager</h2>
</div>
<div class="row" style="margin-top: 50px;">
<div class="col s12 m6 offset-m3">
<div class="card">
<div class="card login-card">
<div class="card-content">
<span class="card-title">Login</span>
{{if .error}}
<div class="red-text">{{index .error 0}}</div>
{{end}}
<form action="/login" method="POST">
<div class="input-field">
<input id="username" name="username" type="text" class="validate" required>
Expand All @@ -36,17 +56,21 @@
<input id="password" name="password" type="password" class="validate" required>
<label for="password">Password</label>
</div>
<button class="btn waves-effect waves-light" type="submit">
Login
<i class="material-icons right">send</i>
</button>
<div class="center-button">
<button class="btn waves-effect waves-light" type="submit">
Login
</button>
</div>
</form>
</div>
</div>
{{if .error}}
<div class="red-text center-align">{{.error}}</div>
{{end}}
</div>
</div>
</div>
<!-- Materialize JavaScript -->
<script src="/static/materialize/materialize.js"></script>
</body>
</html>
</html>

0 comments on commit 6092786

Please sign in to comment.