Make server out of SS script
This commit is contained in:
157
cmd/ss/server.go
Normal file
157
cmd/ss/server.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/stephenafamo/bob"
|
||||
"gitlab.artefactual.com/dcosme/am-scripts/assets"
|
||||
"gitlab.artefactual.com/dcosme/am-scripts/database/mcp/models"
|
||||
)
|
||||
|
||||
func server() error {
|
||||
fileServer := http.FileServer(http.FS(assets.Assets))
|
||||
http.Handle("/assets/", http.StripPrefix("/assets/", fileServer))
|
||||
state := &State{
|
||||
Theme: ThemeLight,
|
||||
Mysql: &Service{
|
||||
Name: "Mysql",
|
||||
Status: "Disconnected",
|
||||
},
|
||||
}
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
Home(state).Render(w)
|
||||
})
|
||||
http.HandleFunc("/upload", state.uploadInput)
|
||||
http.HandleFunc("/mysql", state.connectDB)
|
||||
http.HandleFunc("/report", state.report)
|
||||
|
||||
slog.Info("listening", "addr", "4001")
|
||||
err := http.ListenAndServe(":4001", http.DefaultServeMux)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (state *State) report(w http.ResponseWriter, r *http.Request) {
|
||||
mu := sync.Mutex{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
err := func() error {
|
||||
if len(state.Input) == 0 && state.Report == nil {
|
||||
return errors.New("need input before creating report")
|
||||
}
|
||||
if state.Mysql.Status != "Connected" {
|
||||
return errors.New("need database online")
|
||||
}
|
||||
|
||||
slog.Info("creating report")
|
||||
for idx, record := range state.Input {
|
||||
q := models.LocationsPackages.Query()
|
||||
like := fmt.Sprintf("%%%s%%", record)
|
||||
q.Apply(models.SelectWhere.LocationsPackages.CurrentPath.Like(like))
|
||||
res, err := q.All(context.Background(), state.db)
|
||||
assertNoErr(err)
|
||||
|
||||
row := []string{record}
|
||||
for _, r := range res {
|
||||
slog.Info("AIP Found: " + r.CurrentPath)
|
||||
row = append(row, r.CurrentPath)
|
||||
}
|
||||
state.Report[idx] = row
|
||||
}
|
||||
|
||||
return Report(state).Render(w)
|
||||
}()
|
||||
if err != nil {
|
||||
state.Err = err
|
||||
slog.Error(err.Error())
|
||||
Report(state).Render(w)
|
||||
}
|
||||
}
|
||||
|
||||
func (state *State) connectDB(w http.ResponseWriter, r *http.Request) {
|
||||
err := func() error {
|
||||
state.Mysql.Err = nil
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
connString := r.PostFormValue("mysql")
|
||||
slog.Info("connecting mysql", "conn", connString)
|
||||
db, err := openDB(connString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", connString, err)
|
||||
}
|
||||
state.db = bob.NewDB(db)
|
||||
slog.Info("connected to database")
|
||||
state.Mysql.Status = "Connected"
|
||||
state.Mysql.URL = connString
|
||||
|
||||
return Home(state).Render(w)
|
||||
}()
|
||||
if err != nil {
|
||||
state.Mysql.Err = err
|
||||
slog.Error(err.Error())
|
||||
Home(state).Render(w)
|
||||
}
|
||||
}
|
||||
|
||||
func (state *State) uploadInput(w http.ResponseWriter, r *http.Request) {
|
||||
err := func() error {
|
||||
type InputFile struct {
|
||||
Name string `json:"name"`
|
||||
Contents string `json:"contents"`
|
||||
Mime string `json:"mime"`
|
||||
}
|
||||
type UploadPayload struct {
|
||||
InputFile []InputFile `json:"input-file"`
|
||||
}
|
||||
var payload UploadPayload
|
||||
err := bind(&payload, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(payload.InputFile) != 1 {
|
||||
return fmt.Errorf("exactly one file is allowed to be uploaded, got: %d", len(payload.InputFile))
|
||||
}
|
||||
file := payload.InputFile[0]
|
||||
|
||||
raw := file.Contents
|
||||
content, err := base64.StdEncoding.DecodeString(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lines := strings.Split(strings.TrimSpace(string(content)), "\n")
|
||||
slog.Info("file uploaded", "name", file.Name)
|
||||
state.Input = lines
|
||||
state.Report = make([][]string, len(lines))
|
||||
|
||||
return Home(state).Render(w)
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func bind(v any, r *http.Request) error {
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
json.Unmarshal(body, v)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user