func printResources(ctx *app.Context) { // TODO: Define an interface in package vfs, so this fails // if the interface is changed or renamed. type rooter interface { Root() string } var assets string var templates string if mgr := ctx.App().AssetsManager(); mgr != nil { if r, ok := mgr.VFS().(rooter); ok { assets = r.Root() } } if r, ok := ctx.App().TemplatesFS().(rooter); ok { templates = r.Root() } resources := map[string]string{ "assets": assets, "templates": templates, } data, err := json.Marshal(resources) if err != nil { panic(err) } fmt.Println(string(data)) }
func ListHandler(ctx *app.Context) { var groups []*packageGroup dctx := getEnvironment(ctx) for _, gr := range appDocGroups(ctx) { var groupPackages []*doc.Package for _, v := range gr.Packages { pkgs, err := dctx.ImportPackages(packageDir(dctx, v)) if err != nil { log.Errorf("error importing %s: %s", v, err) continue } groupPackages = append(groupPackages, pkgs...) } if len(groupPackages) > 0 { groups = append(groups, &packageGroup{ Title: gr.Title, Packages: groupPackages, }) } } if len(groups) == 0 { ctx.NotFound("no packages to list") return } title := "Package Index" data := map[string]interface{}{ "Header": title, "Title": title, "Groups": groups, } ctx.MustExecute(PackagesTemplateName, data) }
func afterTask(ctx *app.Context, task *Task, started time.Time, terr *error) { name := task.Name() if err := recover(); err != nil { skip, stackSkip, _, _ := runtimeutil.GetPanic() var buf bytes.Buffer fmt.Fprintf(&buf, "Panic executing task %s: %v\n", name, err) stack := runtimeutil.FormatStack(stackSkip) location, code := runtimeutil.FormatCaller(skip, 5, true, true) if location != "" { buf.WriteString("\n At ") buf.WriteString(location) if code != "" { buf.WriteByte('\n') buf.WriteString(code) buf.WriteByte('\n') } } if stack != "" { buf.WriteString("\nStack:\n") buf.WriteString(stack) } *terr = errors.New(buf.String()) } end := time.Now() running.Lock() defer running.Unlock() c := running.tasks[task] - 1 if c > 0 { running.tasks[task] = c } else { delete(running.tasks, task) } ctx.Logger().Infof("Finished task %s (%d instances now running) at %v (took %v)", name, c, end, end.Sub(started)) }
func redirectToFrom(ctx *app.Context) { from := ctx.FormValue(app.SignInFromParameterName) if from == "" { from = "/" } ctx.Redirect(from, false) }
func testing2(ctx app.Context) { ctx.T("Testing even more translations") var t1 i18n.String = "Var inside function" /// This is a var string declared via cast t2 := i18n.String("Testing var string") fmt.Println(t1, t2) }
func StdListHandler(ctx *app.Context) { dctx := getEnvironment(ctx) allPkgs, err := dctx.ImportPackages(dctx.Join(dctx.Context.GOROOT, "src")) if err != nil { panic(err) } var pkgs []*doc.Package var cmds []*doc.Package for _, v := range allPkgs { if dctx.Base(v.Dir()) == "cmd" { cmds = append(cmds, v) } else { pkgs = append(pkgs, v) } } title := "Go Standard Library" groups := []packageGroup{ {Title: "Go Standard Library", Packages: pkgs}, {Title: "Go Commands", Packages: cmds}, } data := map[string]interface{}{ "Header": title, "Title": title, "Groups": groups, } ctx.MustExecute(PackagesTemplateName, data) }
func decodeResetPayload(ctx *app.Context, payload string) (reflect.Value, error) { se, err := ctx.App().EncryptSigner(Salt) if err != nil { return reflect.Value{}, err } value, err := se.UnsignDecrypt(payload) if err != nil { return reflect.Value{}, err } qs, err := url.ParseQuery(string(value)) if err != nil { return reflect.Value{}, err } userId, err := strconv.ParseInt(qs.Get("u"), 36, 64) if err != nil { return reflect.Value{}, err } ts, err := strconv.ParseInt(qs.Get("t"), 36, 64) if err != nil { return reflect.Value{}, err } if time.Since(time.Unix(ts, 0)) > PasswordResetExpiry { return reflect.Value{}, errResetExpired } user, userVal := newEmptyUser(ctx) ok := ctx.Orm().MustOne(orm.Eq("User.UserId", userId), userVal) if !ok { return reflect.Value{}, errNoSuchUser } return user, nil }
func ArticleListHandler(ctx *app.Context) { data := map[string]interface{}{ "Articles": getArticles(ctx), "Title": ctx.App().Name(), } ctx.MustExecute("list.html", data) }
func signInFacebookTokenHandler(ctx *app.Context, client *oauth2.Client, token *oauth2.Token) { user, err := userFromFacebookToken(ctx, token) if err != nil { panic(err) } ctx.MustSignIn(asGondolaUser(user)) redirectToFrom(ctx) }
func signInGoogleTokenHandler(ctx *app.Context, client *oauth2.Client, token *oauth2.Token) { d := data(ctx) googleApp := d.opts.GoogleApp.Clone(ctx) user, err := userFromGoogleToken(ctx, googleApp, token) if err != nil { panic(err) } ctx.MustSignIn(asGondolaUser(user)) redirectToFrom(ctx) }
func validateNewUsername(ctx *app.Context, username string) error { userType := getUserType(ctx) found, err := ctx.Orm().Exists(ctx.Orm().TypeTable(userType), ByUsername(username)) if err != nil { return err } if found { return i18n.Errorf("username %q is already in use", username) } return nil }
func (m *SimpleMediator) Skip(ctx *app.Context) bool { if m := ctx.R.Method; m != "GET" && m != "HEAD" { return true } c := ctx.Cookies() for _, v := range m.SkipCookies { if c.Has(v) { return true } } return false }
func executeTask(ctx *app.Context, task *Task) (ran bool, err error) { var n int if n, err = numberOfInstances(task); err != nil { return } started := time.Now() ctx.Logger().Infof("Starting task %s (%d instances now running) at %v", task.Name(), n, started) ran = true defer afterTask(ctx, task, started, &err) task.Handler(ctx) return }
func FormErrors(ctx *app.Context, frm *form.Form) { errors := make(map[string]string) for _, v := range frm.Fields() { if ferr := v.Err(); ferr != nil { errors[v.HTMLName] = ferr.Error() } } data := map[string]interface{}{ "errors": errors, } ctx.WriteJSON(data) }
func serveFile(ctx *app.Context, path string) { f, err := os.Open(path) if err != nil { ctx.NotFound("") return } defer f.Close() var modtime time.Time if fi, err := f.Stat(); err == nil { modtime = fi.ModTime() } http.ServeContent(ctx, ctx.R, filepath.Base(path), modtime, f) }
func listUsers(ctx *app.Context) { userVal, ptr := newEmptyUser(ctx) iter := ctx.Orm().All().Iter() w := tabwriter.NewWriter(os.Stdout, 0, 8, 2, '\t', tabwriter.Debug) fmt.Fprint(w, "ID\tUsername\tEmail\tAdmin?\n") for iter.Next(ptr) { val := userVal.Elem().FieldByName("User").Interface().(User) fmt.Fprintf(w, "%d\t%s\t%s\t%v\n", val.UserId, val.Username, val.Email, val.Admin) } if err := w.Flush(); err != nil { panic(err) } }
func windowCallbackHandler(ctx *app.Context, user reflect.Value, callback string) { inWindow := ctx.FormValue("window") != "" if user.IsValid() { ctx.MustSignIn(asGondolaUser(user)) } if inWindow { var payload []byte if user.IsValid() { var err error payload, err = JSONEncode(ctx, user.Interface()) if err != nil { panic(err) } } ctx.MustExecute("js-callback.html", map[string]interface{}{ "Callback": callback, "Payload": payload, }) } else { if user.IsValid() { redirectToFrom(ctx) } else { ctx.MustRedirectReverse(false, app.SignInHandlerName) } } }
func validateNewEmail(ctx *app.Context, email string) (string, error) { addr, err := mail.Validate(email, true) if err != nil { return "", i18n.Errorf("this does not look like a valid email address") } userType := getUserType(ctx) found, err := ctx.Orm().Exists(ctx.Orm().TypeTable(userType), ByEmail(addr)) if err != nil { return "", err } if found { return "", i18n.Errorf("email %q is already in use", addr) } return addr, nil }
func jsSignUpHandler(ctx *app.Context) { d := data(ctx) if !d.allowRegistration() { ctx.NotFound("") return } user, _ := newEmptyUser(ctx) form := SignUpForm(ctx, user) if form.Submitted() && form.IsValid() { saveNewUser(ctx, user) writeJSONEncoded(ctx, user) return } FormErrors(ctx, form) }
// Implementation of the help command for Gondola apps func help(ctx *app.Context) { var cmd string ctx.ParseIndexValue(0, &cmd) if cmd != "" { c := strings.ToLower(cmd) if _, ok := commands[c]; ok { fmt.Fprintf(os.Stderr, "Help for command %s:\n", c) commandHelp(c, -1, os.Stderr) } else { fmt.Fprintf(os.Stderr, "No such command %q\n", cmd) } } else { fmt.Fprintf(os.Stderr, "Commands:\n") commandsHelp(os.Stderr) } }
func jsSignInGoogleHandler(ctx *app.Context) { code := ctx.RequireFormValue(oauth2.Code) redir := "postmessage" // this is the redir value used for G+ JS sign in d := data(ctx) googleApp := d.opts.GoogleApp.Clone(ctx) token, err := googleApp.Exchange(redir, code) if err != nil { panic(err) } user, err := userFromGoogleToken(ctx, googleApp, token) if err != nil { panic(err) } ctx.MustSignIn(asGondolaUser(user)) writeJSONEncoded(ctx, user) }
func jsSignInHandler(ctx *app.Context) { d := data(ctx) if !d.allowDirectSignIn() { ctx.NotFound("") return } signIn := SignIn{} form := form.New(ctx, &signIn) if form.Submitted() && form.IsValid() { user := reflect.ValueOf(signIn.User) ctx.MustSignIn(asGondolaUser(user)) writeJSONEncoded(ctx, user) return } FormErrors(ctx, form) }
func UserImageHandler(ctx *app.Context) { if ImageHandler != nil { ImageHandler(ctx) return } id := ctx.IndexValue(0) format := ctx.IndexValue(1) if lower := strings.ToLower(format); lower != format { ctx.MustRedirectReverse(true, ImageHandlerName, id, lower) return } ctx.SetHeader("Content-Type", "image/"+format) httpserve.NeverExpires(ctx) bs := ctx.Blobstore() if err := bs.Serve(ctx, id, nil); err != nil { panic(err) } }
func gondolaRunTasksHandler(ctx *app.Context) { if ctx.GetHeader("X-Appengine-Cron") != "true" { ctx.Forbidden("") return } pendingTasks.Lock() for _, v := range pendingTasks.tasks { task := v ctx.Go(func(c *app.Context) { if _, err := executeTask(c, task); err != nil { ctx.Logger().Error(err) } }) } pendingTasks.tasks = nil pendingTasks.Unlock() ctx.Wait() }
func makeAssets(ctx *app.Context) { a := ctx.App() if cfg := a.Config(); cfg != nil { cfg.TemplateDebug = false } err := vfs.Walk(a.TemplatesFS(), "/", func(fs vfs.VFS, p string, info os.FileInfo, err error) error { if err != nil || info.IsDir() || p == "" || p[0] == '.' { return err } if _, err := a.LoadTemplate(p); err != nil { log.Errorf("error loading template %s: %s", p, err) } return nil }) if err != nil { log.Errorf("error listing templates: %s", err) } }
func jsSignInFacebookHandler(ctx *app.Context) { req := ctx.FormValue("req") fbApp := data(ctx).opts.FacebookApp.Clone(ctx) resp, err := fbApp.ParseSignedRequest(req) if err != nil { panic(err) } // Let it crash if the data does not have the // specified format, this will make it easier // to find it if it happens. code := resp["code"].(string) token, err := fbApp.Exchange("", code) user, err := userFromFacebookToken(ctx, token) if err != nil { panic(err) } ctx.MustSignIn(asGondolaUser(user)) writeJSONEncoded(ctx, user) }
func ResetHandler(ctx *app.Context) { d := data(ctx) if !d.allowDirectSignIn() { ctx.NotFound("") return } payload := ctx.FormValue("p") var valid bool var expired bool var f *form.Form var user reflect.Value var err error var done bool if payload != "" { user, err = decodeResetPayload(ctx, payload) if err == nil && user.IsValid() { valid = true } else { if err == errResetExpired { expired = true } } } if valid { passwordForm := &PasswordForm{User: user} f = form.New(ctx, passwordForm) if f.Submitted() && f.IsValid() { ctx.Orm().MustSave(user.Interface()) ctx.MustSignIn(asGondolaUser(user)) done = true } } data := map[string]interface{}{ "Valid": valid, "Expired": expired, "Done": done, "User": user, "PasswordForm": f, "Payload": payload, } ctx.MustExecute(ResetTemplateName, data) }
func mightFetchImage(ctx *app.Context, url string, prevId string, prevFormat string, prevURL string) (string, string, string) { if url == prevURL { return prevId, prevFormat, prevURL } if url == "" { if prevId != "" { ctx.Blobstore().Remove(prevId) } return "", "", "" } id, format, err := getImage(ctx, url) if err != nil { // Keep previous return prevId, prevFormat, prevURL } if prevId != "" { ctx.Blobstore().Remove(prevId) } return id, format, url }
func getByUsernameOrEmail(ctx *app.Context, usernameOrEmail string) (interface{}, error) { norm := Normalize(usernameOrEmail) _, userVal := newEmptyUser(ctx) var ok bool o := ctx.Orm() q1 := orm.Eq("User.NormalizedUsername", norm) q2 := orm.Eq("User.NormalizedEmail", norm) if o.Driver().Capabilities()&driver.CAP_OR != 0 { ok = o.MustOne(orm.Or(q1, q2), userVal) } else { ok = o.MustOne(q1, userVal) if !ok { ok = o.MustOne(q2, userVal) } } if !ok { return nil, ErrNoUser } return userVal, nil }
// Create creates a new user user with the given parameters, previously checking that // the given username and email aren't already in use. Note that the user is only created, // no implicit sign in is performed. func Create(ctx *app.Context, username string, email string, pw string) (app.User, error) { if err := validateNewUsername(ctx, username); err != nil { return nil, err } addr, err := validateNewEmail(ctx, email) if err != nil { return nil, err } user, userIface := newEmptyUser(ctx) setUserValue(user, "Username", username) setUserValue(user, "NormalizedUsername", Normalize(username)) setUserValue(user, "Email", addr) setUserValue(user, "NormalizedEmail", Normalize(addr)) setUserValue(user, "Password", password.New(pw)) setUserValue(user, "Created", time.Now().UTC()) if _, err = ctx.Orm().Insert(userIface); err != nil { return nil, err } return userIface.(app.User), nil }