eclipse/cmd/eclipse-httpd/webhooks.go

92 lines
2.3 KiB
Go

// Copyright (C) 2024 Umorpha Systems
// SPDX-License-Identifier: AGPL-3.0-or-later
package main
import (
"encoding/json"
"errors"
"io"
"log"
"net/http"
"os/exec"
"sort"
"git.mothstuff.lol/lukeshu/eclipse/lib/apikeys"
)
type Webhooks struct {
pubKey apikeys.PublicKey
cfgFile string
}
func (o *Webhooks) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := o.serveHTTP(w, r); err != nil {
if err.Code != -100 {
http.Error(w, err.Error(), err.Code)
}
if err.Code/100 == 5 {
log.Printf("error: %q: %v", r.URL, err)
}
}
}
var webhooks = map[string]func(cfg *Webhooks, w http.ResponseWriter, r *http.Request) *_httpError{
"from-gitea": func(cfg *Webhooks, w http.ResponseWriter, r *http.Request) *_httpError {
if r.Method != http.MethodPost {
return httpError(errors.New("only POST is supported"), http.StatusMethodNotAllowed)
}
if err := requireAuthorization(cfg.pubKey, w, r); err != nil {
return err
}
payloadBytes, err := io.ReadAll(r.Body)
if err != nil {
return httpError(err, http.StatusBadRequest)
}
var payload struct {
Repository struct {
SSHURL string `json:"ssh_url"`
CloneURL string `json:"clone_url"`
} `json:"repository"`
}
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
return httpError(err, http.StatusBadRequest)
}
cmd := exec.CommandContext(r.Context(), "eclipse-trigger",
"--config="+cfg.cfgFile,
"--",
payload.Repository.SSHURL,
payload.Repository.CloneURL)
cmd.Stdout = w
cmd.Stderr = w
if err := cmd.Run(); err != nil {
return httpError(err, http.StatusInternalServerError)
}
return nil
},
}
var tmplWebhooks = pageTemplate("webhooks.html.tmpl")
func (o *Webhooks) serveHTTP(w http.ResponseWriter, r *http.Request) *_httpError {
if r.URL.Path == "" {
if r.Method != http.MethodGet {
return httpError(errors.New("only GET is supported"), http.StatusMethodNotAllowed)
}
names := make([]string, 0, len(webhooks))
for name := range webhooks {
names = append(names, name)
}
sort.Strings(names)
if err := tmplWebhooks.Execute(w, map[string]any{"Webhooks": names}); err != nil {
return writeOrServerError(err)
}
}
callback := webhooks[r.URL.Path]
if callback == nil {
return httpNotFound()
}
return callback(o, w, r)
}