258 lines
9.1 KiB
Go
258 lines
9.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
func MPE_IsProject(input *Payload) (projectnumber string, project_name string) {
|
|
// this will attempt to extract a project number from the "targetpath" element. If it's able to determine a folder contains a project number, we'll return it.
|
|
|
|
// var path_data map[string]json.RawMessage
|
|
project_regex, _ := regexp.Compile(`(^[0-9]{1,3})`) // regex to match against
|
|
|
|
// err := json.Unmarshal((input.Data), &path_data)
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// fmt.Println("oops")
|
|
// return
|
|
// }
|
|
|
|
path := string(input.Data[0].PathData.TargetPath)
|
|
split_path, _ := filepath.Split(path)
|
|
split_path = filepath.Clean(split_path)
|
|
|
|
separated_path := strings.Split(split_path, "/") //turn this into an array (slice?) to parse
|
|
var sb strings.Builder
|
|
// iterate through the path_data map. We want to find all strings that start with a number.
|
|
for _, value := range separated_path {
|
|
matched := project_regex.MatchString(value)
|
|
if matched {
|
|
// if we match the Regex above, write values to SB. This will give us a string like "73|10 Office Of Somone|153 HelpMe|002 Phase 2"
|
|
|
|
sb.WriteString(value + "|")
|
|
|
|
} else {
|
|
// DoNothing
|
|
}
|
|
} // end of loop
|
|
|
|
// now to assemble project number and project name from the resulting values...
|
|
project_text := sb.String()
|
|
project_slice := strings.Split(project_text, "|")
|
|
// first value should be a digit, if not this can't be a project
|
|
isProject0, err := regexp.MatchString(`(^[0-9])`, project_slice[0])
|
|
if err != nil {
|
|
fmt.Printf("err.Error(): %v\n", err.Error())
|
|
}
|
|
isProject1, err := regexp.MatchString(`(^[0-9])`, project_slice[1])
|
|
if err != nil {
|
|
fmt.Printf("err.Error(): %v\n", err.Error())
|
|
}
|
|
isProject2, err := regexp.MatchString(`(^[0-9])`, project_slice[2])
|
|
if err != nil {
|
|
fmt.Printf("err.Error(): %v\n", err.Error())
|
|
}
|
|
// isProject, _ = regexp.MatchString(`(^[0-9])`, project_slice[3])
|
|
if isProject0 && isProject1 && isProject2 {
|
|
|
|
project_regex, _ := regexp.Compile(`(^[0-9]{1,3})`) // regex to match against
|
|
regex_tidy_string, _ := regexp.Compile(`[-_]+|^\s`) //regex to tidy up folder paths
|
|
client_section := regex_tidy_string.ReplaceAllString(project_slice[1], "") // remove fancy chars from Client Name
|
|
project_section := regex_tidy_string.ReplaceAllString(project_regex.ReplaceAllString(project_slice[2], ""), " ") // remove leading-digits
|
|
project_section_digits := strings.Split(regex_tidy_string.ReplaceAllString(project_slice[2], " "), " ") //split on space for MOST file folders...
|
|
|
|
sb.Reset() // reset string builder so I can use it again!
|
|
sb.WriteString(project_slice[0]) // 73
|
|
sb.WriteString(strings.Split(client_section, " ")[0] + "-") // 7310 -- Client Name
|
|
sb.WriteString(project_section_digits[0]) // 7310-10
|
|
|
|
// do we have a third section of the project number?
|
|
project_third := strings.Split(project_slice[3], " ")[0]
|
|
project_third_match, _ := regexp.MatchString(`(^[0-9]{1,3})`, project_third)
|
|
/* TODO: Better identification of the third number.
|
|
Currently seeing paths such as "/shared/n-data/12/34 test/45 ProjectName/deliverables/05 geotech" generating project numbers of 1234-45-05,
|
|
where it should be 1234-45
|
|
|
|
This is due to the RegEx Match looking for all folders that start with digits, and not being concerned about where they are in the string.
|
|
|
|
|
|
*/
|
|
if project_third_match {
|
|
// if we have a third section, then add another section to the project number, and append to the project name
|
|
third_project_name := project_regex.ReplaceAllString(project_slice[3], "") // 7310-10-153
|
|
project_name = project_section + "-" + regex_tidy_string.ReplaceAllString(third_project_name, "") // remove project digits from beginning of string and append
|
|
project_third = regex_tidy_string.ReplaceAllString(project_third, " ")
|
|
sb.WriteString("-" + project_third)
|
|
|
|
} else {
|
|
project_name = project_section // remove project digits from beginning of string
|
|
|
|
}
|
|
|
|
projectnumber = sb.String() // I should now have a project number!
|
|
|
|
} else {
|
|
return "NotAProject", "NoPath"
|
|
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func MPE_ValidateForward(in *Payload) bool {
|
|
// decode targetPath data. Will return TRUE if the last section of the path contains "External Share" or "ExternalShare". This would indicate that we SHOULD forward this request onward.
|
|
// var path_data map[string]json.RawMessage
|
|
// err := json.Unmarshal((in.Data), &path_data)
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// fmt.Println("oops")
|
|
// return false
|
|
// }
|
|
|
|
path := string(in.Data[0].PathData.TargetPath)
|
|
split_path, last := filepath.Split(path)
|
|
split_path = filepath.Clean(split_path)
|
|
|
|
matched, _ := regexp.MatchString(`ExternalShare|External Share`, last)
|
|
|
|
return matched
|
|
}
|
|
|
|
func readDataStream(resp http.ResponseWriter, request *http.Request) {
|
|
// reqBody, _ := io.ReadAll(request.Body)
|
|
colorReset := "\033[0m"
|
|
|
|
// colorRed := "\033[31m"
|
|
colorGreen := "\033[32m"
|
|
colorYellow := "\033[33m"
|
|
colorBlue := "\033[34m"
|
|
// colorPurple := "\033[35m"
|
|
// colorCyan := "\033[36m"
|
|
// colorWhite := "\033[37m"
|
|
|
|
var log_values log_data
|
|
var request_body Payload // init request_body as data type Payload - uses custom structs
|
|
body_string, _ := io.ReadAll(request.Body) // ready Body Data
|
|
log_values.BodyData = string(body_string) // prep for logging
|
|
// fmt.Printf("%+v\n", log_values) // debug code to show JASON data coming in
|
|
|
|
err := json.Unmarshal(body_string, &request_body)
|
|
if err != nil {
|
|
var error_sb strings.Builder
|
|
error_sb.WriteString("ERROR in JSON\n")
|
|
error_sb.WriteString(string(body_string))
|
|
error_sb.WriteString("\n--Error from Unmarshal: ")
|
|
error_sb.WriteString(err.Error())
|
|
fmt.Print(error_sb.String())
|
|
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
resp.Write([]byte(error_sb.String()))
|
|
|
|
return
|
|
}
|
|
|
|
log_values.EventID = request_body.Data[0].EventID
|
|
log_values.EventType = request_body.Data[0].EventType
|
|
log_values.User = request_body.Data[0].User.DisplayName
|
|
log_values.TargetPath = colorGreen + request_body.Data[0].PathData.TargetPath + colorReset
|
|
|
|
// fmt.Printf("%+v\n", log_values) // output log values to stdout - first round
|
|
|
|
var MPE_ShouldFoward = MPE_ValidateForward(&request_body)
|
|
var MPE_ProjectNumber, MPE_ProjectName = MPE_IsProject(&request_body)
|
|
|
|
log_values.ExternalShare = MPE_ShouldFoward
|
|
log_values.MPE_ProjectName = colorYellow + MPE_ProjectName + colorReset
|
|
log_values.MPE_ProjectNumber = colorBlue + MPE_ProjectNumber + colorReset
|
|
|
|
fmt.Printf("%+v\n", log_values) // output log values to stdout - second round
|
|
|
|
// Collect EventID, JSON Content, and return values into data object to be logged to screen. Validate data visually for a bit against "live" webhook data.
|
|
|
|
// TODO: Once Data validation / Struct is built, pass data off to next Webhook URL for processing.
|
|
}
|
|
|
|
func HealthCheck(resp http.ResponseWriter, request *http.Request) {
|
|
var t = time.Now().String()
|
|
var MessageText = t + ": Health Check from " + request.RemoteAddr
|
|
// reqBody, _ := io.ReadAll(request.Body)
|
|
|
|
fmt.Println(http.StatusOK, MessageText)
|
|
resp.WriteHeader(http.StatusOK)
|
|
resp.Write([]byte(MessageText))
|
|
}
|
|
|
|
func CatchError(resp http.ResponseWriter, request *http.Request) {
|
|
var LogText = "got bad request from " + request.RemoteAddr + ". Method: " + request.Method
|
|
fmt.Println(http.StatusBadRequest, LogText)
|
|
var MessageText = "Invalid Request, please read the docs..."
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
resp.Write([]byte(MessageText))
|
|
|
|
}
|
|
|
|
func handleRequests() {
|
|
// Start new Mux router
|
|
mainrouter := mux.NewRouter().StrictSlash(true)
|
|
|
|
mainrouter.HandleFunc("/", readDataStream).Methods("POST")
|
|
mainrouter.HandleFunc("/healthcheck", HealthCheck).Methods("GET")
|
|
mainrouter.HandleFunc("/", CatchError)
|
|
|
|
log.Fatal(http.ListenAndServe(":10000", mainrouter))
|
|
|
|
}
|
|
|
|
func main() {
|
|
var t = time.Now().String()
|
|
fmt.Println("MPE x Egnyte x PowerApps - Mux Router starting: " + t)
|
|
handleRequests()
|
|
}
|
|
|
|
type Payload struct {
|
|
Data []EG_Data `json:"data"`
|
|
}
|
|
type User struct {
|
|
ID int `json:"id"`
|
|
ClientIDHash string `json:"clientIdHash"`
|
|
DisplayName string `json:"displayName"`
|
|
Username string `json:"username"`
|
|
Email string `json:"email"`
|
|
ImpersonatedBy string `json:"impersonatedBy"`
|
|
}
|
|
type PathData struct {
|
|
SourcePath string `json:"sourcePath"`
|
|
TargetPath string `json:"targetPath"`
|
|
}
|
|
type EG_Data struct {
|
|
EventID string `json:"eventId"`
|
|
Domain string `json:"domain"`
|
|
Timestamp int64 `json:"timestamp"`
|
|
User User `json:"user"`
|
|
ActionSource string `json:"actionSource"`
|
|
WebhookID string `json:"webhookId"`
|
|
EventType string `json:"eventType"`
|
|
PathData PathData `json:"data"`
|
|
}
|
|
|
|
type log_data struct {
|
|
EventID string
|
|
User string
|
|
EventType string
|
|
TargetPath string
|
|
ExternalShare bool
|
|
MPE_ProjectNumber string
|
|
MPE_ProjectName string
|
|
BodyData string
|
|
}
|