forked from adamm/autogits
170 lines
4.1 KiB
Go
170 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
|
|
"src.opensuse.org/autogits/common"
|
|
)
|
|
|
|
type Status struct {
|
|
Context string `json:"context"`
|
|
State string `json:"state"`
|
|
TargetUrl string `json:"target_url"`
|
|
}
|
|
|
|
type StatusInput struct {
|
|
State string `json:"state"`
|
|
TargetUrl string `json:"target_url"`
|
|
}
|
|
|
|
func main() {
|
|
configFile := flag.String("config", "", "status proxy config file")
|
|
flag.Parse()
|
|
|
|
if *configFile == "" {
|
|
common.LogError("missing required argument config")
|
|
return
|
|
}
|
|
|
|
config, err := ReadConfigFile(*configFile)
|
|
|
|
if err != nil {
|
|
common.LogError("Failed to read config file", err)
|
|
return
|
|
}
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.Handle("/repos/{owner}/{repo}/statuses/{sha}", ConfigMiddleWare(config)(http.HandlerFunc(StatusProxy)))
|
|
|
|
common.LogInfo("server up and listening on :3000")
|
|
err = http.ListenAndServe(":3000", mux)
|
|
|
|
if err != nil {
|
|
common.LogError("Server failed to start up", err)
|
|
}
|
|
|
|
}
|
|
|
|
func StatusProxy(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == http.MethodPost {
|
|
config, ok := r.Context().Value(configKey).(*Config)
|
|
|
|
if !ok {
|
|
common.LogError("Config missing from context")
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
header := r.Header.Get("Authorization")
|
|
if header == "" {
|
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
token_arr := strings.Split(header, " ")
|
|
if len(token_arr) != 2 {
|
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
if !strings.EqualFold(token_arr[0], "Bearer") {
|
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
token := token_arr[1]
|
|
|
|
if !slices.Contains(config.Keys, token) {
|
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
owner := r.PathValue("owner")
|
|
repo := r.PathValue("repo")
|
|
sha := r.PathValue("sha")
|
|
|
|
if !ok {
|
|
common.LogError("Failed to get config from context, is it set?")
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
}
|
|
|
|
posturl := fmt.Sprintf("%s/repos/%s/%s/statuses/%s", config.ForgeEndpoint, owner, repo, sha)
|
|
decoder := json.NewDecoder(r.Body)
|
|
var statusinput StatusInput
|
|
err := decoder.Decode(&statusinput)
|
|
if err != nil {
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
return
|
|
}
|
|
status := Status{
|
|
Context: "Build in obs",
|
|
State: statusinput.State,
|
|
TargetUrl: statusinput.TargetUrl,
|
|
}
|
|
|
|
status_payload, err := json.Marshal(status)
|
|
|
|
if err != nil {
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
return
|
|
}
|
|
client := &http.Client{}
|
|
req, err := http.NewRequest("POST", posturl, bytes.NewBuffer(status_payload))
|
|
|
|
if err != nil {
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
return
|
|
}
|
|
ForgeToken := os.Getenv("GITEA_TOKEN")
|
|
|
|
if ForgeToken == "" {
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
common.LogError("GITEA_TOKEN was not set, all requests will fail")
|
|
return
|
|
}
|
|
|
|
req.Header.Add("Content-Type", "Content-Type")
|
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", ForgeToken))
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
common.LogError(fmt.Sprintf("Request to forge endpoint failed: %v", err))
|
|
http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(resp.StatusCode)
|
|
|
|
/*
|
|
the commented out section sets every key
|
|
value from the headers, unsure if this
|
|
leaks information from gitea
|
|
|
|
for k, v := range resp.Header {
|
|
for _, vv := range v {
|
|
w.Header().Add(k, vv)
|
|
}
|
|
}
|
|
*/
|
|
|
|
_, err = io.Copy(w, resp.Body)
|
|
if err != nil {
|
|
common.LogError("Error copying response body: %v", err)
|
|
}
|
|
} else {
|
|
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
}
|