zdravko/internal/server/handlers/settings_hooks.go

271 lines
6 KiB
Go

package handlers
import (
"context"
"fmt"
"net/http"
"time"
"github.com/go-playground/validator/v10"
"github.com/gosimple/slug"
"github.com/labstack/echo/v4"
"github.com/mentos1386/zdravko/database/models"
"github.com/mentos1386/zdravko/internal/server/services"
"github.com/mentos1386/zdravko/pkg/script"
"github.com/mentos1386/zdravko/web/templates/components"
)
type CreateHook struct {
Name string `validate:"required"`
Schedule string `validate:"required,cron"`
Script string `validate:"required"`
}
type UpdateHook struct {
Schedule string `validate:"required,cron"`
Script string `validate:"required"`
}
type HookWithState struct {
*models.Hook
State models.HookState
}
type SettingsHooks struct {
*Settings
Hooks []*HookWithState
History []struct {
CreatedAt time.Time
Status string
Note string
}
}
type SettingsHook struct {
*Settings
Hook *HookWithState
History []*services.HookHistory
}
type SettingsHookCreate struct {
*Settings
ExampleScript string
ExampleFilter string
}
func (h *BaseHandler) SettingsHooksGET(c echo.Context) error {
cc := c.(AuthenticatedContext)
hooks, err := services.GetHooks(context.Background(), h.db)
if err != nil {
return err
}
hooksWithState := make([]*HookWithState, len(hooks))
for i, hook := range hooks {
state, err := services.GetHookState(context.Background(), h.temporal, hook.Id)
if err != nil {
h.logger.Error("Failed to get hook state", "error", err)
state = models.HookStateUnknown
}
hooksWithState[i] = &HookWithState{
Hook: hook,
State: state,
}
}
return c.Render(http.StatusOK, "settings_hooks.tmpl", &SettingsHooks{
Settings: NewSettings(
cc.Principal.User,
GetPageByTitle(SettingsPages, "Hooks"),
[]*components.Page{GetPageByTitle(SettingsPages, "Hooks")},
),
Hooks: hooksWithState,
})
}
func (h *BaseHandler) SettingsHooksDescribeGET(c echo.Context) error {
cc := c.(AuthenticatedContext)
slug := c.Param("id")
hook, err := services.GetHook(context.Background(), h.db, slug)
if err != nil {
return err
}
status, err := services.GetHookState(context.Background(), h.temporal, hook.Id)
if err != nil {
return err
}
hookWithStatus := &HookWithState{
Hook: hook,
State: status,
}
history, err := services.GetHookHistoryForHook(context.Background(), h.temporal, slug)
if err != nil {
return err
}
maxElements := 10
if len(history) < maxElements {
maxElements = len(history)
}
return c.Render(http.StatusOK, "settings_hooks_describe.tmpl", &SettingsHook{
Settings: NewSettings(
cc.Principal.User,
GetPageByTitle(SettingsPages, "Hooks"),
[]*components.Page{
GetPageByTitle(SettingsPages, "Hooks"),
{
Path: fmt.Sprintf("/settings/hooks/%s", slug),
Title: "Describe",
Breadcrumb: hook.Name,
},
}),
Hook: hookWithStatus,
History: history[:maxElements],
})
}
func (h *BaseHandler) SettingsHooksDescribeDELETE(c echo.Context) error {
slug := c.Param("id")
err := services.DeleteHook(context.Background(), h.db, slug)
if err != nil {
return err
}
err = services.DeleteHookSchedule(context.Background(), h.temporal, slug)
if err != nil {
return err
}
return c.Redirect(http.StatusSeeOther, "/settings/hooks")
}
func (h *BaseHandler) SettingsHooksDisableGET(c echo.Context) error {
slug := c.Param("id")
hook, err := services.GetHook(context.Background(), h.db, slug)
if err != nil {
return err
}
err = services.SetHookState(context.Background(), h.temporal, hook.Id, models.HookStatePaused)
if err != nil {
return err
}
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/hooks/%s", slug))
}
func (h *BaseHandler) SettingsHooksEnableGET(c echo.Context) error {
slug := c.Param("id")
hook, err := services.GetHook(context.Background(), h.db, slug)
if err != nil {
return err
}
err = services.SetHookState(context.Background(), h.temporal, hook.Id, models.HookStateActive)
if err != nil {
return err
}
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/hooks/%s", slug))
}
func (h *BaseHandler) SettingsHooksDescribePOST(c echo.Context) error {
ctx := context.Background()
hookId := c.Param("id")
update := UpdateHook{
Schedule: c.FormValue("schedule"),
Script: script.EscapeString(c.FormValue("script")),
}
err := validator.New(validator.WithRequiredStructEnabled()).Struct(update)
if err != nil {
return err
}
hook, err := services.GetHook(ctx, h.db, hookId)
if err != nil {
return err
}
hook.Schedule = update.Schedule
hook.Script = update.Script
err = services.UpdateHook(
ctx,
h.db,
hook,
)
if err != nil {
return err
}
err = services.CreateOrUpdateHookSchedule(ctx, h.temporal, hook)
if err != nil {
return err
}
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/hooks/%s", hookId))
}
func (h *BaseHandler) SettingsHooksCreateGET(c echo.Context) error {
cc := c.(AuthenticatedContext)
return c.Render(http.StatusOK, "settings_hooks_create.tmpl", &SettingsHookCreate{
Settings: NewSettings(
cc.Principal.User,
GetPageByTitle(SettingsPages, "Hooks"),
[]*components.Page{
GetPageByTitle(SettingsPages, "Hooks"),
GetPageByTitle(SettingsPages, "Hooks Create"),
},
),
ExampleScript: h.examples.Hook,
})
}
func (h *BaseHandler) SettingsHooksCreatePOST(c echo.Context) error {
ctx := context.Background()
hookId := slug.Make(c.FormValue("name"))
create := CreateHook{
Name: c.FormValue("name"),
Schedule: c.FormValue("schedule"),
Script: script.EscapeString(c.FormValue("script")),
}
err := validator.New(validator.WithRequiredStructEnabled()).Struct(create)
if err != nil {
return err
}
hook := &models.Hook{
Name: create.Name,
Id: hookId,
Schedule: create.Schedule,
Script: create.Script,
}
err = services.CreateHook(
ctx,
h.db,
hook,
)
if err != nil {
return err
}
err = services.CreateOrUpdateHookSchedule(ctx, h.temporal, hook)
if err != nil {
return err
}
return c.Redirect(http.StatusSeeOther, "/settings/hooks")
}