func handleSetupChange(rw http.ResponseWriter, req *http.Request) { hilevelConf, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } if !xsrftoken.Valid(req.FormValue("token"), serverKey, "user", "wizardSave") { http.Error(rw, "Form expired. Press back and reload form.", http.StatusBadRequest) log.Printf("invalid xsrf token=%q", req.FormValue("token")) return } hasChanged := false var el interface{} publish := jsonconfig.Obj{} for k, v := range req.Form { if _, ok := hilevelConf[k]; !ok { if k != "gallery" && k != "blog" { continue } } switch k { case "https", "shareHandler": b, err := strconv.ParseBool(v[0]) if err != nil { httputil.ServeError(rw, req, fmt.Errorf("%v field expects a boolean value", k)) } el = b default: el = v[0] } if reflect.DeepEqual(hilevelConf[k], el) { continue } hasChanged = true hilevelConf[k] = el } // "publish" wasn't checked yet if !reflect.DeepEqual(hilevelConf["publish"], publish) { hilevelConf["publish"] = publish hasChanged = true } if hasChanged { err = rewriteConfig(&hilevelConf, osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } err = osutil.RestartProcess() if err != nil { log.Fatal("Failed to restart: " + err.Error()) http.Error(rw, "Failed to restart process", 500) return } } sendWizard(rw, req, hasChanged) }
func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) { ck, err := r.Cookie("user") if err != nil { http.Error(w, fmt.Sprintf("Cookie expired, or CSRF attempt. Restart from %s%s%s", h.scheme, h.host, h.prefix), http.StatusBadRequest) h.Printf("Cookie expired, or CSRF attempt on callback.") return } code := r.FormValue("code") if code == "" { httputil.ServeError(w, r, errors.New("No oauth code parameter in callback URL")) return } h.Printf("successful authentication: %v", r.URL.RawQuery) br, tk, err := fromState(r) if err != nil { httputil.ServeError(w, r, err) return } if !xsrftoken.Valid(tk, h.xsrfKey, ck.Value, br.String()) { httputil.ServeError(w, r, fmt.Errorf("Invalid xsrf token: %q", tk)) return } oAuthConf := h.oAuthConfig() tok, err := oAuthConf.Exchange(oauth2.NoContext, code) if err != nil { httputil.ServeError(w, r, fmt.Errorf("could not obtain a token: %v", err)) return } h.Printf("successful authorization with token: %v", tok) instConf, err := h.instanceConf(br) if err != nil { httputil.ServeError(w, r, err) return } depl := &Deployer{ Client: oAuthConf.Client(oauth2.NoContext, tok), Conf: instConf, } if found := h.serveOldInstance(w, br, depl); found { return } if err := h.recordState(br, &creationState{ InstConf: br, }); err != nil { httputil.ServeError(w, r, err) return } if h.debug { // We simulate an instance creation, without actually ever doing anything on Google Cloud, // by sleeping for a while. Then, as we would do in the real case, we record a creation // state (but a made-up one). In the meantime, the progress page/animation is served as // usual. go func() { time.Sleep(7 * time.Second) if err := h.recordState(br, &creationState{ InstConf: br, InstAddr: "fake.instance.com", Success: true, CertFingerprintSHA1: "XXXXXXXXXXXXXXXXXXXX", CertFingerprintSHA256: "YYYYYYYYYYYYYYYYYYYY", }); err != nil { h.Printf("Could not record creation state for %v: %v", br, err) h.recordStateErrMu.Lock() defer h.recordStateErrMu.Unlock() h.recordStateErr[br.String()] = err } }() h.serveProgress(w, br) return } go func() { inst, err := depl.Create(context.TODO()) state := &creationState{ InstConf: br, } if err != nil { h.Printf("could not create instance: %v", err) switch e := err.(type) { case instanceExistsError: state.Err = fmt.Sprintf("%v %v", e, helpDeleteInstance) case projectIDError: state.Err = fmt.Sprintf("%v", e) default: state.Err = fmt.Sprintf("%v. %v", err, fileIssue(br.String())) } } else { state.InstAddr = addr(inst) state.Success = true state.CertFingerprintSHA1 = depl.certFingerprints["SHA-1"] state.CertFingerprintSHA256 = depl.certFingerprints["SHA-256"] } if err := h.recordState(br, state); err != nil { h.Printf("Could not record creation state for %v: %v", br, err) h.recordStateErrMu.Lock() defer h.recordStateErrMu.Unlock() h.recordStateErr[br.String()] = err } }() h.serveProgress(w, br) }
func (sh *SyncHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if req.Method == "POST" { if req.FormValue("mode") == "validate" { token := req.FormValue("token") if xsrftoken.Valid(token, auth.ProcessRandom(), "user", "runFullValidate") { sh.startFullValidation() http.Redirect(rw, req, "./", http.StatusFound) } } http.Error(rw, "Bad POST request", http.StatusBadRequest) return } // TODO: remove this lock and instead just call currentStatus, // and transition to using that here. sh.mu.Lock() defer sh.mu.Unlock() f := func(p string, a ...interface{}) { fmt.Fprintf(rw, p, a...) } now := time.Now() f("<h1>Sync Status (for %s to %s)</h1>", sh.fromName, sh.toName) f("<p><b>Current status: </b>%s</p>", html.EscapeString(sh.status)) if sh.idle { return } f("<h2>Stats:</h2><ul>") f("<li>Source: %s</li>", html.EscapeString(storageDesc(sh.from))) f("<li>Target: %s</li>", html.EscapeString(storageDesc(sh.to))) f("<li>Blobs synced: %d</li>", sh.totalCopies) f("<li>Bytes synced: %d</li>", sh.totalCopyBytes) f("<li>Blobs yet to copy: %d</li>", len(sh.needCopy)) f("<li>Bytes yet to copy: %d</li>", sh.bytesRemain) if !sh.recentCopyTime.IsZero() { f("<li>Most recent copy: %s (%v ago)</li>", sh.recentCopyTime.Format(time.RFC3339), now.Sub(sh.recentCopyTime)) } clarification := "" if len(sh.needCopy) == 0 && sh.totalErrors > 0 { clarification = "(all since resolved)" } f("<li>Previous copy errors: %d %s</li>", sh.totalErrors, clarification) f("</ul>") f("<h2>Validation</h2>") if len(sh.vshards) == 0 { f("Validation disabled") token := xsrftoken.Generate(auth.ProcessRandom(), "user", "runFullValidate") f("<form method='POST'><input type='hidden' name='mode' value='validate'><input type='hidden' name='token' value='%s'><input type='submit' value='Start validation'></form>", token) } else { f("<p>Background scan of source and destination to ensure that the destination has everything the source does, or is at least enqueued to sync.</p>") f("<ul>") f("<li>Shards complete: %d/%d (%.1f%%)</li>", sh.vshardDone, len(sh.vshards), 100*float64(sh.vshardDone)/float64(len(sh.vshards))) f("<li>Source blobs seen: %d</li>", sh.vsrcCount) f("<li>Source bytes seen: %d</li>", sh.vsrcBytes) f("<li>Dest blobs seen: %d</li>", sh.vdestCount) f("<li>Dest bytes seen: %d</li>", sh.vdestBytes) f("<li>Blobs found missing + fixed: %d</li>", sh.vmissing) if len(sh.vshardErrs) > 0 { f("<li>Validation errors: %s</li>", sh.vshardErrs) } f("</ul>") } if len(sh.copying) > 0 { f("<h2>Currently Copying</h2><ul>") copying := make([]blob.Ref, 0, len(sh.copying)) for br := range sh.copying { copying = append(copying, br) } sort.Sort(blob.ByRef(copying)) for _, br := range copying { f("<li>%s</li>\n", sh.copying[br]) } f("</ul>") } recentErrors := make([]blob.Ref, 0, len(sh.recentErrors)) for _, br := range sh.recentErrors { if _, ok := sh.needCopy[br]; ok { // Only show it in the web UI if it's still a problem. Blobs that // have since succeeded just confused people. recentErrors = append(recentErrors, br) } } if len(recentErrors) > 0 { f("<h2>Recent Errors</h2><p>Blobs that haven't successfully copied over yet, and their last errors:</p><ul>") for _, br := range recentErrors { fail := sh.lastFail[br] f("<li>%s: %s: %s</li>\n", br, fail.when.Format(time.RFC3339), html.EscapeString(fail.err.Error())) } f("</ul>") } }
func (h *DeployHandler) serveCallback(w http.ResponseWriter, r *http.Request) { ck, err := r.Cookie("user") if err != nil { http.Error(w, fmt.Sprintf("Cookie expired, or CSRF attempt. Restart from %s://%s%s", h.scheme, h.host, h.prefix), http.StatusBadRequest) h.logger.Printf("Cookie expired, or CSRF attempt on callback.") return } code := r.FormValue("code") if code == "" { h.serveError(w, r, errors.New("No oauth code parameter in callback URL")) return } h.logger.Printf("successful authentication: %v", r.URL.RawQuery) br, tk, err := fromState(r) if err != nil { h.serveError(w, r, err) return } if !xsrftoken.Valid(tk, h.xsrfKey, ck.Value, br.String()) { h.serveError(w, r, fmt.Errorf("Invalid xsrf token: %q", tk)) return } oAuthConf := h.oAuthConfig() tok, err := oAuthConf.Exchange(oauth2.NoContext, code) if err != nil { h.serveError(w, r, fmt.Errorf("could not obtain a token: %v", err)) return } h.logger.Printf("successful authorization with token: %v", tok) instConf, err := h.instanceConf(br) if err != nil { h.serveError(w, r, err) return } depl := &Deployer{ Client: oAuthConf.Client(oauth2.NoContext, tok), Conf: instConf, Logger: h.logger, } if found := h.serveOldInstance(w, br, depl); found { return } if err := h.recordState(br, &creationState{ InstConf: br, }); err != nil { h.serveError(w, r, err) return } go func() { inst, err := depl.Create(context.TODO()) state := &creationState{ InstConf: br, } if err != nil { h.logger.Printf("could not create instance: %v", err) switch e := err.(type) { case instanceExistsError: state.Err = fmt.Sprintf("%v %v", e, helpDeleteInstance) case projectIDError: state.Err = fmt.Sprintf("%v", e) default: state.Err = fmt.Sprintf("%v. %v", err, fileIssue(br.String())) } } else { state.InstAddr = addr(inst) state.Success = true state.CertFingerprintSHA1 = depl.certFingerprints["SHA-1"] state.CertFingerprintSHA256 = depl.certFingerprints["SHA-256"] } if err := h.recordState(br, state); err != nil { h.logger.Printf("Could not record creation state for %v: %v", br, err) h.recordStateErrMu.Lock() defer h.recordStateErrMu.Unlock() h.recordStateErr[br.String()] = err } }() h.serveProgress(w, br) }