Have got logout working

This commit is contained in:
Leon Mika 2026-02-25 22:30:28 +11:00
parent 01c6e9de87
commit b7e0269e9d
7 changed files with 66 additions and 10 deletions

View file

@ -0,0 +1,9 @@
import { Controller } from "@hotwired/stimulus"
export default class LogoutController extends Controller {
async logout(ev) {
ev.preventDefault();
await fetch(`/logout`, { method: 'POST' });
window.location.href = '/login';
}
}

View file

@ -3,8 +3,10 @@ import { Application } from "@hotwired/stimulus";
import ToastController from "./controllers/toast";
import PostlistController from "./controllers/postlist";
import PosteditController from "./controllers/postedit";
import LogoutController from "./controllers/logout";
window.Stimulus = Application.start()
Stimulus.register("toast", ToastController);
Stimulus.register("postlist", PostlistController);
Stimulus.register("postedit", PosteditController);
Stimulus.register("logout", LogoutController);

View file

@ -29,12 +29,21 @@ func (lh *LoginHandler) Login(c fiber.Ctx) error {
return nil
}
func (lh *LoginHandler) Logout(c fiber.Ctx) error {
sess := session.FromContext(c)
sess.Destroy()
return c.Redirect().To("/login")
}
func (lh *LoginHandler) DoLogin(c fiber.Ctx) error {
var req struct {
Username string `form:"username"`
Password string `form:"password"`
LoginChallenge string `form:"_login_challenge"`
}
if err := c.Bind().Body(&req); err != nil {
return c.Status(fiber.StatusBadRequest).SendString("Failed to parse request body")
}
if req.Username == "" || req.Password == "" {
return c.Status(fiber.StatusBadRequest).SendString("Username and password are required")
@ -43,7 +52,7 @@ func (lh *LoginHandler) DoLogin(c fiber.Ctx) error {
sess := session.FromContext(c)
challenge, _ := sess.Get("_login_challenge").(string)
if challenge == req.LoginChallenge {
if challenge != req.LoginChallenge {
return c.Redirect().To("/login")
}

21
main.go
View file

@ -2,6 +2,7 @@ package main
import (
"context"
"flag"
"html"
"html/template"
"log"
@ -29,6 +30,10 @@ import (
)
func main() {
flagUser := flag.String("user", "", "select user to perform operation on")
flagPasswd := flag.String("passwd", "", "change password for user")
flag.Parse()
cfg, err := config.LoadConfig()
if err != nil {
log.Fatal(err)
@ -43,9 +48,20 @@ func main() {
authSvc := auth.New(dbp)
publisherSvc := publisher.New(dbp)
publisherQueue := publisher.NewQueue(publisherSvc)
publisherQueue.Start(context.Background())
postService := posts.New(dbp, publisherQueue)
// CLI tools
if *flagPasswd != "" && *flagUser != "" {
user, err := authSvc.SetPassword(context.Background(), *flagUser, *flagPasswd)
if err != nil {
log.Fatal(err)
}
log.Printf("Password changed for user %s\n", user.Username)
return
}
publisherQueue.Start(context.Background())
fiberTemplate := fiber_html.New("./views", ".html")
fiberTemplate.Funcmap["sub"] = func(x, y int) int { return x - y }
fiberTemplate.Funcmap["markdown"] = func() func(s string) template.HTML {
@ -108,7 +124,8 @@ func main() {
ph := handlers.PostsHandler{PostService: postService}
app.Get("/login", lh.Login)
app.Post("/login", lh.Login)
app.Post("/login", lh.DoLogin)
app.Post("/logout", lh.Logout)
siteGroup := app.Group("/sites/:siteID", middleware.AuthUser(authSvc), middleware.RequiresSite(dbp))

View file

@ -34,3 +34,13 @@ func (s *Service) Login(ctx context.Context, username, password string) (models.
func (s *Service) GetUser(ctx context.Context, userID int64) (models.User, error) {
return s.db.SelectUserByID(ctx, userID)
}
func (s *Service) SetPassword(ctx context.Context, username, password string) (models.User, error) {
user, err := s.db.SelectUserByUsername(ctx, username)
if err != nil {
return models.User{}, err
}
user.SetPassword(password)
return user, s.db.SaveUser(ctx, &user)
}

View file

@ -18,8 +18,17 @@
</div>
-->
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
<button class="btn btn-outline-success" type="submit">Search</button>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ .user.Username }}
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" data-controller="logout" data-action="logout#logout">Logout</a></li>
</ul>
</div>
</form>
</div>
</div>

View file

@ -2,15 +2,15 @@
<div class="text-center mb-3">
<h3>Weiro Login</h3>
</div>
<input type="hidden" name="_login_challenge" value="{{ .challenge }}">
<form action="/login" method="post">
<input type="hidden" name="_login_challenge" value="{{ .challenge }}">
<div class="mb-2">
<label for="login_username" class="form-label">Login</label>
<input type="email" class="form-control" id="login_username">
<label for="username" class="form-label">Login</label>
<input type="text" class="form-control" name="username" id="username">
</div>
<div class="mb-3">
<label for="login_password" class="form-label">Password</label>
<input type="password" class="form-control" id="login_password">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" name="password" id="password">
</div>
<div class="mb-3 text-end">
<input type="submit" class="btn btn-primary" value="Login">