mirror of https://gitlab.com/ngerakines/tavern.git
179 lines
4.3 KiB
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"))
|
|
}
|