tavern/web/handler_configure.go

179 lines
4.3 KiB
Go

package web
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
"go.uber.org/zap"
"github.com/ngerakines/tavern/common"
"github.com/ngerakines/tavern/errors"
"github.com/ngerakines/tavern/storage"
)
func (h handler) configure(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
trans, transOK := c.Get("trans")
if !transOK {
panic("trans not found in context")
}
data := gin.H{
"flashes": getFlashes(session),
"Trans": trans,
}
user, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
if errors.Is(err, errors.UserSessionNotFoundError{}) {
if err = appendFlashError(session, "Not Authenticated"); err != nil {
h.hardFail(c, errors.NewCannotSaveSessionError(err))
return
}
c.Redirect(http.StatusFound, "/")
return
}
h.hardFail(c, err)
return
}
data["user"] = user
data["authenticated"] = true
data["fed_config"] = map[string]bool{
"reply_collection_updates": h.fedConfig.AllowFollowObject,
"auto_accept_followers": h.fedConfig.AllowAutoAcceptFollowers,
}
data["user_config"] = map[string]bool{
"reply_collection_updates": user.ReplyCollectionUpdates,
"auto_accept_followers": user.AcceptFollowers,
}
serverActorRowID, err := h.storage.ActorRowIDForActorID(ctx, fmt.Sprintf("https://%s/server", h.domain))
if err != nil {
h.hardFail(c, err)
return
}
acls, err := h.storage.ListACLsByScopes(ctx, []uuid.UUID{user.ActorID, serverActorRowID})
if err != nil {
h.hardFail(c, err)
return
}
data["acls"] = acls
if err = session.Save(); err != nil {
h.hardFail(c, err)
return
}
c.HTML(http.StatusOK, "configure", data)
}
func (h handler) saveUserSettings(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
user, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
h.hardFail(c, err)
return
}
h.logger.Info("saving user settings",
zap.String("auto_accept_followers", c.PostForm("auto_accept_followers")),
zap.String("reply_collection_updates", c.PostForm("reply_collection_updates")),
)
err = storage.TransactionalStorage(ctx, h.storage, func(tx storage.Storage) error {
txErr := tx.UpdateUserAutoAcceptFollowers(ctx, user.ID, c.PostForm("auto_accept_followers") == "checked")
if txErr != nil {
return txErr
}
return tx.UpdateUserReplyCollectionUpdates(ctx, user.ID, c.PostForm("reply_collection_updates") == "checked")
})
if err != nil {
h.hardFail(c, err)
return
}
c.Redirect(http.StatusFound, h.url("configure"))
}
func (h handler) createACL(c *gin.Context) {
if c.PostForm("validate") == "validate" {
h.validateACL(c)
return
}
session := sessions.Default(c)
ctx := c.Request.Context()
user, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
h.hardFail(c, err)
return
}
wild := strings.ContainsRune(c.PostForm("target"), '*')
txErr := storage.TransactionalStorage(ctx, h.storage, func(tx storage.Storage) error {
action, err := strconv.Atoi(c.PostForm("action"))
if err != nil {
return err
}
_, err = tx.RecordACL(ctx, user.ActorID, c.PostForm("target"), storage.ACLAction(action), wild)
return err
})
if txErr != nil {
h.hardFail(c, txErr)
return
}
h.flashSuccessOrFail(c, h.url("configure"), "ACL created")
}
func (h handler) validateACL(c *gin.Context) {
session := sessions.Default(c)
ctx := c.Request.Context()
user, err := h.storage.GetUserBySession(ctx, session)
if err != nil {
h.hardFail(c, err)
return
}
target := c.PostForm("target")
domain := strings.TrimPrefix(target, "https://")
if i := strings.IndexRune(domain, '/'); i > -1 {
domain = domain[:i]
}
var matchSet common.MatcherSet
txErr := storage.TransactionalStorage(ctx, h.storage, func(tx storage.Storage) error {
acls, err := tx.ListACLsByScopesAndWildTargets(ctx, []uuid.UUID{user.ActorID, h.serverActorRowID}, []string{domain, target})
if err != nil {
return err
}
matchSet = acls.ToMatchSet(common.NewUniqueUUIDs().With(h.serverActorRowID), true)
return nil
})
if txErr != nil {
h.hardFail(c, txErr)
return
}
if matchSet.Allow(domain, target) {
h.flashSuccessOrFail(c, h.url("configure"), "ACL allow")
return
}
h.flashErrorOrFail(c, h.url("configure"), fmt.Errorf("ACL deny"))
}