From 4da00d680ea6cc42a92027eab4dca7798037057b Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Tue, 30 Jan 2018 09:46:51 +0100 Subject: [PATCH] Use html/template to generate HTML output. This also removes the authentication requirement. --- kraftakt.go | 121 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 38 deletions(-) diff --git a/kraftakt.go b/kraftakt.go index 1f3ac98..976bbd4 100644 --- a/kraftakt.go +++ b/kraftakt.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "html/template" "io/ioutil" "net/http" "sync" @@ -21,15 +22,24 @@ import ( var delayedHandleNotifications = delay.Func("handleNotifications", handleNotifications) +var templates *template.Template + func init() { http.Handle("/fitbit/connect", AuthenticatedHandler(fitbitConnectHandler)) http.Handle("/fitbit/grant", AuthenticatedHandler(fitbitGrantHandler)) - http.Handle("/fitbit/notify", ContextHandler(fitbitNotifyHandler)) http.Handle("/fitbit/disconnect", AuthenticatedHandler(fitbitDisconnectHandler)) http.Handle("/google/connect", AuthenticatedHandler(googleConnectHandler)) http.Handle("/google/grant", AuthenticatedHandler(googleGrantHandler)) http.Handle("/google/disconnect", AuthenticatedHandler(googleDisconnectHandler)) - http.Handle("/", AuthenticatedHandler(indexHandler)) + // unauthenticated + http.Handle("/fitbit/notify", ContextHandler(fitbitNotifyHandler)) + http.Handle("/", ContextHandler(indexHandler)) + + t, err := template.ParseGlob("templates/*.html") + if err != nil { + panic(err) + } + templates = t } // ContextHandler implements http.Handler @@ -82,47 +92,37 @@ func (hndl AuthenticatedHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques } } -func indexHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error { - _, err := u.Token(ctx, "Fitbit") - if err != nil && err != datastore.ErrNoSuchEntity { - return err - } - haveFitbitToken := err == nil - - _, err = u.Token(ctx, "Google") - if err != nil && err != datastore.ErrNoSuchEntity { - return err +func indexHandler(ctx context.Context, w http.ResponseWriter, _ *http.Request) error { + var templateData struct { + HaveFitbit bool + HaveGoogleFit bool + *app.User } - haveGoogleToken := err == nil - - fmt.Fprintln(w, "Kraftakt") - fmt.Fprintln(w, "

Kraftakt

") + templateName := "main.html" - fmt.Fprintln(w, "

Kraftakt copies your Fitbit data to Google Fit, seconds after you sync.

") + if gaeUser := user.Current(ctx); gaeUser != nil { + templateName = "loggedin.html" - fmt.Fprintf(w, "

Hello %s

\n", user.Current(ctx).Email) - fmt.Fprintln(w, "") - fmt.Fprintln(w, "") - - return nil + return templates.ExecuteTemplate(w, templateName, &templateData) } func fitbitConnectHandler(_ context.Context, w http.ResponseWriter, r *http.Request, _ *app.User) error { @@ -134,7 +134,7 @@ func fitbitGrantHandler(ctx context.Context, w http.ResponseWriter, r *http.Requ if err := fitbit.ParseToken(ctx, r, u); err != nil { return err } - c, err := fitbit.NewClient(ctx, "-", u) + c, err := fitbit.NewClient(ctx, "", u) if err != nil { return err } @@ -154,8 +154,35 @@ func fitbitGrantHandler(ctx context.Context, w http.ResponseWriter, r *http.Requ return nil } -func googleSetupHandler(w http.ResponseWriter, r *http.Request) { +func fitbitDisconnectHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error { + c, err := fitbit.NewClient(ctx, "", u) + if err != nil { + return err + } + + var errs appengine.MultiError + if err := c.Unsubscribe(ctx); err != nil { + errs = append(errs, fmt.Errorf("Unsubscribe() = %v", err)) + } + + if err := c.DeleteToken(ctx); err != nil { + errs = append(errs, fmt.Errorf("DeleteToken() = %v", err)) + } + if len(errs) != 0 { + return errs + } + + redirectURL := r.URL + redirectURL.Path = "/" + redirectURL.RawQuery = "" + redirectURL.Fragment = "" + http.Redirect(w, r, redirectURL.String(), http.StatusTemporaryRedirect) + return nil +} + +func googleConnectHandler(_ context.Context, w http.ResponseWriter, r *http.Request, _ *app.User) error { http.Redirect(w, r, gfit.AuthURL(), http.StatusTemporaryRedirect) + return nil } func googleGrantHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error { @@ -171,6 +198,24 @@ func googleGrantHandler(ctx context.Context, w http.ResponseWriter, r *http.Requ return nil } +func googleDisconnectHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, u *app.User) error { + c, err := gfit.NewClient(ctx, u) + if err != nil { + return err + } + + if err := c.DeleteToken(ctx); err != nil { + return err + } + + redirectURL := r.URL + redirectURL.Path = "/" + redirectURL.RawQuery = "" + redirectURL.Fragment = "" + http.Redirect(w, r, redirectURL.String(), http.StatusTemporaryRedirect) + return nil +} + // fitbitNotifyHandler is called by Fitbit whenever there are updates to a // subscription. It verifies the payload, splits it into individual // notifications and adds it to the taskqueue service. -- 2.11.0