keiji-ctl.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "flag"
  6. "fmt"
  7. "io"
  8. "log"
  9. "mime/multipart"
  10. "net/http"
  11. "net/url"
  12. "os"
  13. "path"
  14. "path/filepath"
  15. "git.aetherial.dev/aeth/keiji/pkg/auth"
  16. "git.aetherial.dev/aeth/keiji/pkg/controller"
  17. "git.aetherial.dev/aeth/keiji/pkg/storage"
  18. _ "github.com/mattn/go-sqlite3"
  19. )
  20. func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
  21. file, err := os.Open(path)
  22. if err != nil {
  23. return nil, err
  24. }
  25. defer file.Close()
  26. body := &bytes.Buffer{}
  27. writer := multipart.NewWriter(body)
  28. part, err := writer.CreateFormFile(paramName, filepath.Base(path))
  29. if err != nil {
  30. return nil, err
  31. }
  32. _, err = io.Copy(part, file)
  33. if err != nil {
  34. log.Fatal(err)
  35. }
  36. for key, val := range params {
  37. _ = writer.WriteField(key, val)
  38. }
  39. err = writer.Close()
  40. if err != nil {
  41. return nil, err
  42. }
  43. req, err := http.NewRequest("POST", uri, body)
  44. req.Header.Set("Content-Type", writer.FormDataContentType())
  45. return req, err
  46. }
  47. // authenticate and get the cookie needed to make updates
  48. func authenticate(url, username, password string) *http.Cookie {
  49. client := http.Client{}
  50. b, _ := json.Marshal(auth.Credentials{Username: username, Password: password})
  51. req, _ := http.NewRequest(http.MethodPost, url, bytes.NewReader(b))
  52. req.Header.Add("Content-Type", "application/json")
  53. resp, err := client.Do(req)
  54. if err != nil {
  55. log.Fatal("auth failed: ", err)
  56. }
  57. defer resp.Body.Close()
  58. if resp.StatusCode > 200 {
  59. msg, _ := io.ReadAll(resp.Body)
  60. log.Fatal("Invalid credentials or server error: ", string(msg), "\n Status code: ", resp.StatusCode)
  61. }
  62. cookies := resp.Cookies()
  63. for i := range cookies {
  64. if cookies[i].Name == controller.AUTH_COOKIE_NAME {
  65. return cookies[i]
  66. }
  67. }
  68. log.Fatal("Auth cookie not found.")
  69. return nil
  70. }
  71. // prepare the auth cookie
  72. func prepareCookie(address string) *http.Cookie {
  73. parsedAddr, err := url.Parse(address)
  74. dn := parsedAddr.Hostname()
  75. if err != nil {
  76. log.Fatal("unparseable address: ", address, " error: ", err)
  77. }
  78. var preparedCookie *http.Cookie
  79. if cookie == "" {
  80. log.Fatal("Cookie cannot be empty.")
  81. } else {
  82. preparedCookie = &http.Cookie{Value: cookie, Name: controller.AUTH_COOKIE_NAME, Domain: dn}
  83. }
  84. return preparedCookie
  85. }
  86. var pngFile string
  87. var redirect string
  88. var text string
  89. var col string
  90. var cmd string
  91. var address string
  92. var cookie string
  93. func main() {
  94. flag.StringVar(&pngFile, "png", "", "The location of the PNG to upload")
  95. flag.StringVar(&redirect, "redirect", "", "the website that the navbar will redirect to")
  96. flag.StringVar(&text, "text", "", "the text to display on the menu item")
  97. flag.StringVar(&col, "col", "", "the column to add/populate the admin table item under")
  98. flag.StringVar(&cmd, "cmd", "", "the 'command' for the seed program to use, currently supports options 'admin', 'menu', and 'asset', 'nav'")
  99. flag.StringVar(&address, "address", "https://aetherial.dev", "override the url to contact.")
  100. flag.StringVar(&cookie, "cookie", "", "pass a cookie to bypass direct authentication")
  101. flag.Parse()
  102. client := http.Client{}
  103. switch cmd {
  104. case "auth":
  105. cookie := authenticate(fmt.Sprintf("%s/login", address), os.Getenv("KEIJI_USERNAME"), os.Getenv("KEIJI_PASSWORD"))
  106. fmt.Println(cookie.Value)
  107. case "asset":
  108. b, err := os.ReadFile(pngFile)
  109. if err != nil {
  110. log.Fatal(err)
  111. }
  112. _, fileName := path.Split(pngFile)
  113. item := storage.Asset{
  114. Name: fileName,
  115. Data: b,
  116. }
  117. data, _ := json.Marshal(item)
  118. req, _ := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/admin/asset", address), bytes.NewReader(data))
  119. req.AddCookie(prepareCookie(address))
  120. req.Header.Add("Content-Type", "application/json")
  121. resp, err := client.Do(req)
  122. if err != nil {
  123. fmt.Println("There was an error performing the desired request: ", err.Error())
  124. os.Exit(1)
  125. }
  126. if resp.StatusCode > 200 {
  127. defer resp.Body.Close()
  128. b, _ := io.ReadAll(resp.Body)
  129. fmt.Println("There was an error performing the desired request: ", string(b))
  130. os.Exit(2)
  131. }
  132. fmt.Println("navigation bar item upload successfully.")
  133. os.Exit(0)
  134. case "nav":
  135. fmt.Println(string(pngFile))
  136. _, fileName := path.Split(pngFile)
  137. extraParams := map[string]string{
  138. "link": fileName,
  139. "redirect": redirect,
  140. }
  141. req, err := newfileUploadRequest(address+"/admin/navbar", extraParams, "file", pngFile)
  142. if err != nil {
  143. log.Fatal(err)
  144. }
  145. req.AddCookie(prepareCookie(address))
  146. resp, err := client.Do(req)
  147. if err != nil {
  148. fmt.Println("There was an error performing the desired request: ", err.Error())
  149. os.Exit(1)
  150. }
  151. if resp.StatusCode > 200 {
  152. defer resp.Body.Close()
  153. b, _ := io.ReadAll(resp.Body)
  154. fmt.Println("There was an error performing the desired request: ", string(b))
  155. os.Exit(2)
  156. }
  157. fmt.Println("png item upload successfully.")
  158. os.Exit(0)
  159. case "menu":
  160. b, _ := json.Marshal(storage.LinkPair{Text: text, Link: redirect})
  161. req, _ := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/admin/menu", address), bytes.NewReader(b))
  162. req.AddCookie(prepareCookie(address))
  163. req.Header.Add("Content-Type", "application/json")
  164. resp, err := client.Do(req)
  165. if err != nil {
  166. fmt.Println("There was an error performing the desired request: ", err.Error())
  167. os.Exit(1)
  168. }
  169. if resp.StatusCode > 200 {
  170. defer resp.Body.Close()
  171. b, _ := io.ReadAll(resp.Body)
  172. fmt.Println("There was an error performing the desired request: ", string(b))
  173. os.Exit(3)
  174. }
  175. fmt.Println("menu item uploaded successfully.")
  176. os.Exit(0)
  177. case "admin":
  178. tables := make(map[string][]storage.TableData)
  179. adminPage := storage.AdminPage{Tables: tables}
  180. adminPage.Tables[col] = append(adminPage.Tables[col], storage.TableData{Link: redirect, DisplayName: text})
  181. b, _ := json.Marshal(adminPage)
  182. req, _ := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/admin/panel", address), bytes.NewReader(b))
  183. req.AddCookie(prepareCookie(address))
  184. req.Header.Add("Content-Type", "application/json")
  185. resp, err := client.Do(req)
  186. if err != nil {
  187. fmt.Println("There was an error performing the desired request: ", err.Error())
  188. os.Exit(1)
  189. }
  190. if resp.StatusCode > 200 {
  191. defer resp.Body.Close()
  192. b, _ := io.ReadAll(resp.Body)
  193. fmt.Println("There was an error performing the desired request: ", string(b))
  194. os.Exit(4)
  195. }
  196. fmt.Println("admin item added successfully.")
  197. os.Exit(0)
  198. }
  199. }