github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/upspinsos/server.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "encoding/json" 9 "fmt" 10 "html/template" 11 "io/ioutil" 12 "log" 13 "net/http" 14 15 "github.com/gorilla/mux" 16 "github.com/u-root/u-root/pkg/sos" 17 ) 18 19 const ( 20 DefHtmlPage = ` 21 <head> 22 <style> 23 table { 24 font-family: arial, sans-serif; 25 border-collapse: collapse; 26 width: 100%; 27 } 28 td, th { 29 border: 1px solid #dddddd; 30 text-align: left; 31 padding: 8px; 32 } 33 input { 34 font-size: 120%; 35 } 36 </style> 37 <script> 38 function sendEdit() { 39 fetch("http://localhost:{{.Port}}/edit", { 40 method: 'Post' 41 }) 42 .then(r => r.json()) 43 .then( s => { 44 if (s !== null) { 45 alert(s.Error); 46 window.location.reload(); 47 } 48 else { 49 window.location.reload(); 50 } 51 }) 52 .catch(err => alert(err)) 53 } 54 function sendSubmit() { 55 username = document.getElementById("user").value 56 dirserver = document.getElementById("dir").value 57 storeserver = document.getElementById("store").value 58 secretseed = document.getElementById("seed").value 59 fetch("http://localhost:{{.Port}}/submit", { 60 method: 'Post', 61 headers: { 62 'Accept': 'application/json', 63 'Content-Type': 'application/json' 64 }, 65 body: JSON.stringify({ 66 User: username, 67 Dir: dirserver, 68 Store: storeserver, 69 Seed: secretseed 70 }) 71 }) 72 .then(r => r.json()) 73 .then( s => { 74 if (s !== null) { 75 alert(s.Error); 76 window.location.reload(); 77 } 78 else { 79 window.location.reload(); 80 } 81 }) 82 .catch(err => alert(err)) 83 } 84 85 function setFieldsOnLoad(config) { 86 if (config) { 87 disableFields(); 88 } 89 else { 90 enableFields(); 91 } 92 } 93 94 function enableFields() { 95 fields = document.getElementsByClassName("text"); 96 for(let field of fields) { 97 field.removeAttribute("disabled") 98 } 99 document.getElementById("button").setAttribute("value", "Submit"); 100 document.getElementById("button").setAttribute("onclick", "sendSubmit()"); 101 } 102 function disableFields() { 103 fields = document.getElementsByClassName("text"); 104 for(let field of fields) { 105 field.setAttribute("disabled", "true") 106 } 107 document.getElementById("button").setAttribute("value", "Edit"); 108 document.getElementById("button").setAttribute("onclick", "sendEdit()"); 109 } 110 111 </script> 112 </head> 113 <body onload="setFieldsOnLoad({{.Configured}})"> 114 <!-- Copy to local variables --> 115 {{$user := .User}} 116 {{$dir := .Dir}} 117 {{$store := .Store}} 118 {{$seed := .Seed}} 119 <h1>Upspin</h1> 120 <table style="width:100%"> 121 <tr> 122 <th>Username</th> 123 <th>Dir Server</th> 124 <th>Store Server</th> 125 <th>Secret Seed</th> 126 <th></th> 127 </tr> 128 <tr> 129 <td><input type="text" id="user" class="text" value="{{$user}}"></td> 130 <td><input type="text" id="dir" class="text" value="{{$dir}}"></td> 131 <td><input type="text" id="store" class="text" value="{{$store}}"></td> 132 <td><input type="text" id="seed" class="text" value="{{$seed}}"></td> 133 <td><input type="submit" id="button" class="btn"></td> 134 </tr> 135 </table> 136 </body> 137 ` 138 ) 139 140 type UpspinServer struct { 141 service *UpspinService 142 } 143 144 var ( 145 Port uint 146 ) 147 148 func (us *UpspinServer) editHandle(w http.ResponseWriter, r *http.Request) { 149 us.service.ToggleFlag() 150 json.NewEncoder(w).Encode(nil) 151 } 152 153 type UpspinAcctJsonMsg struct { 154 User string 155 Dir string 156 Store string 157 Seed string 158 } 159 160 func (us *UpspinServer) submitHandle(w http.ResponseWriter, r *http.Request) { 161 us.service.ToggleFlag() 162 var msg UpspinAcctJsonMsg 163 decoder := json.NewDecoder(r.Body) 164 defer r.Body.Close() 165 if err := decoder.Decode(&msg); err != nil { 166 log.Printf("error: %v", err) 167 w.WriteHeader(http.StatusBadRequest) 168 json.NewEncoder(w).Encode(struct{ Error string }{err.Error()}) 169 return 170 } 171 if err := us.service.SetConfig(msg); err != nil { 172 log.Printf("error: %v", err) 173 w.WriteHeader(http.StatusInternalServerError) 174 json.NewEncoder(w).Encode(struct{ Error string }{err.Error()}) 175 return 176 } 177 json.NewEncoder(w).Encode(nil) 178 } 179 180 func (us *UpspinServer) displayStateHandle(w http.ResponseWriter, r *http.Request) { 181 us.service.Update() 182 upspinData := struct { 183 Configured bool 184 User string 185 Dir string 186 Store string 187 Seed string 188 Port uint 189 }{us.service.Configured, us.service.User, us.service.Dir, us.service.Store, us.service.Seed, Port} 190 var tmpl *template.Template 191 file, err := ioutil.ReadFile(sos.HTMLPath("upspin.html")) 192 if err == nil { 193 html := string(file) 194 tmpl = template.Must(template.New("SoS").Parse(html)) 195 } else { 196 tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage)) 197 } 198 tmpl.Execute(w, upspinData) 199 } 200 201 func (us *UpspinServer) buildRouter() *mux.Router { 202 r := mux.NewRouter() 203 r.HandleFunc("/", us.displayStateHandle).Methods("GET") 204 r.HandleFunc("/edit", us.editHandle).Methods("POST") 205 r.HandleFunc("/submit", us.submitHandle).Methods("POST") 206 r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css"))))) 207 return r 208 } 209 210 func (us *UpspinServer) Start() { 211 listener, port, err := sos.GetListener() 212 if err != nil { 213 log.Fatalf("error: %v", err) 214 } 215 Port = port 216 fmt.Println(sos.StartServiceServer(us.buildRouter(), "upspin", listener, Port)) 217 } 218 219 func NewUpspinServer(service *UpspinService) *UpspinServer { 220 return &UpspinServer{ 221 service: service, 222 } 223 }