func getResponseHelper(req *wcg.Request) ResponseHelper { app := req.Local(LOCAL_APP_KEY).(*App) if strings.HasPrefix(req.URL().Path, "/api") { return app.Api } return app.Page }
func fetchPost(res *wcg.Response, req *wcg.Request, blog *models.Blog) (*models.Post, error) { driver := models.NewPostDriver(gae.NewContext(req), req.Logger) id := req.Param("post_id") blogId := req.Param("blog_id") post, err := driver.FindPostById(id, blogId) if err != nil { if err == models.ErrPostNotFound { res.WriteHeader(404) res.WriteString("Not found") res.End() return nil, err } res.RenderInternalError(err.Error()) return nil, err } if post.PostState() != models.PostStatePublished { if post.OwnerId != req.User.Id() { res.WriteHeader(404) res.WriteString("Not found") res.End() return nil, err } } return post, err }
// Returns a Context Object. func NewContext(req *wcg.Request) appengine.Context { ctx := req.Local("__gaetest__context") if ctx != nil { return ctx.(appengine.Context) } return appengine.NewContext(req.HttpRequest()) }
func queryShows(res *wcg.Response, req *wcg.Request, q *datastore.Query) (*showQueryResult, error) { var appCtx = lib.NewAppContextFromRequest(req) var showList []event.Show var basePath = req.HttpRequest().URL.Path per_page := 12 // Restict to 12 due to view rendering. page := wcg.ParseInt(req.Query("page"), 0, 0, wcg.ParseIntMax) if _, err := q.Offset(page * per_page).Limit(per_page).GetAll(&showList); err != nil { return nil, err } if showList == nil { return &showQueryResult{ Shows: make([]EventShow, 0), }, nil } if list, err := NewEventShowList(appCtx, showList); err != nil { return nil, err } else { p := &showQueryResult{ Shows: list, Current: fmt.Sprintf("%s?page=%d&n=%d", basePath, page, per_page), } // prev url if page > 0 { p.Previous = fmt.Sprintf("%s?page=%d&n=%d", basePath, page-1, per_page) } // next url if len(p.Shows) == per_page { p.Next = fmt.Sprintf("%s?page=%d&n=%d", basePath, page+1, per_page) } return p, nil } }
func fetchPostForUpdate(req *wcg.Request, res *wcg.Response, blog *models.Blog) (*models.Post, error) { driver := models.NewPostDriver(gae.NewContext(req), req.Logger) id := req.Param("post_id") blogId := req.Param("blog_id") post, err := driver.FindPostById(id, blogId) if err != nil { if err == models.ErrPostNotFound { res.WriteHeader(404) res.WriteString("Not found") res.End() return nil, err } res.RenderInternalError(err.Error()) return nil, err } if blog.Id != post.BlogId { res.WriteHeader(403) res.WriteString("You could not manage that blog.") res.End() } if post.OwnerId != req.User.Id() { res.WriteHeader(403) res.WriteString("You could not manage this post.") res.End() return nil, err } return post, err }
func GetCurrentApp(req *wcg.Request) *App { if app := req.Local(LOCAL_APP_KEY); app != nil { return app.(*App) } else { return nil } }
func (ph *PageHelper) Forbidden(res *wcg.Response, req *wcg.Request) { res.SetLocal("Ref", req.URL().RequestURI()) res.TemplatesWithStatus( 403, nil, "403.html", "header.html", "footer.html", ) }
func crawlSpecifiedMembers(res *wcg.Response, req *wcg.Request, app *App) { member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } crawl(res, req, member, app) }
// HTTP 201 Created func (api *ApiHelper) Created(res *wcg.Response, req *wcg.Request, id string) { loc := path.Join(req.URL().Path, fmt.Sprintf("%s.json", id)) res.WriteJsonWithStatus(201, nil, map[string]interface{}{ "ok": true, "id": id, "location": wcg.AbsoluteUrl(req, loc), }) }
func indexSpecifiedMember(res *wcg.Response, req *wcg.Request, app *App) { var appCtx = lib.NewAppContextFromRequest(req) member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } num := wcg.ParseInt(req.Param("n"), 0, 0, wcg.ParseIntMax) if num == 0 { num = wcg.ParseIntMax } // Crawling crawler := ameblo.NewCrawler(appCtx.NewHttpClient()) prefix := strings.TrimSuffix(member.BlogUrl, ".html") // xxxx.html => xxxx-{num}.html entries := make([]*ameblo.AmebloEntry, 0) for i := 1; i < num; i += 1 { url := fmt.Sprintf("%s-%d.html", prefix, i) req.Logger.Info("Indexing from %s ... ", url) newentries, err := crawler.CrawlEntryList(url) if err != nil { lib.InternalError(res, req, err) return } if len(newentries) > 20 { panic(fmt.Errorf("Unexpected number of entries (%d) are returned during indexing.", len(newentries))) } if len(newentries) == 0 { break } if len(newentries) < 20 { entries = append(entries, newentries...) break } if len(entries) > 0 && entries[len(entries)-1].Url == newentries[len(newentries)-1].Url { break } entries = append(entries, newentries...) } // Save and return resutls results := make([]string, 0) for _, ent := range entries { ent.Owner = member.Name results = append(results, ent.Url) } if err := updateIndexes(appCtx, entries); err != nil { req.Logger.Error("Failed to update the entry: %v", err) lib.InternalError(res, req, err) // stopped. } else { time.Sleep(10 * time.Second) // TODO: wait for all indexes are updated on datastore. mc := appCtx.NewMemcacheDriver() mckey := fmt.Sprintf(MC_KEY_HISTORY, app.Key, member.Name) mc.Delete(mckey) res.WriteJson(results) } }
func loadEvent(app *App, req *wcg.Request, key string) (*event.Event, error) { var e event.Event d := NewEventDriver(lib.NewAppContextFromRequest(req)) if err := d.Get(d.NewKey(req.Param(key), 0, nil), &e); err != nil { return nil, err } else { return &e, nil } }
func updateAttributesFromForm(res *wcg.Response, req *wcg.Request, e *event.Event) error { var err error if err = eventFormValidator.Eval(req.HttpRequest().PostForm); err != nil { return err } e.Title = req.Form("title") e.Link = req.Form("link") e.ImageLink = req.Form("image_link") e.YAKeyword = req.Form("ya_keyword") e.EventType = event.ParseEventType(req.Form("event_type")) return nil }
func sendToBigQuery(req *wcg.Request) error { var errors = make([]error, 0) var svc *bigquery.Service var records []*wcg.LogRecord data := make(map[string][]*bigquery.TableDataInsertAllRequestRows) if tmp := req.Local(requestLocalLogCacheKey); tmp == nil { return nil } else { records = tmp.([]*wcg.LogRecord) } svc, err := bq.NewService(req) if err != nil { return err } for _, r := range records { tableId, row, err := bqTransform(r) if err != nil { errors = append(errors, err) continue } if rows, ok := data[tableId]; ok { rows = append(rows, row) } else { data[tableId] = []*bigquery.TableDataInsertAllRequestRows{row} } } for tableId, rows := range data { ret, err := svc.Tabledata.InsertAll( LogSinkConfig.BigqueryProject, LogSinkConfig.BigqueryDataset, tableId, &bigquery.TableDataInsertAllRequest{ Kind: "bigquery#tableDataInsertAllRequest", Rows: rows, }).Do() if err != nil { errors = append(errors, err) continue } if len(ret.InsertErrors) > 0 { errors = append(errors, fmt.Errorf("InsertErrors: %s", ret.InsertErrors[0])) continue } } if len(errors) > 0 { return logTransmissionError(errors) } return nil }
func ahAuthHandler(res *wcg.Response, req *wcg.Request) bool { if strings.HasPrefix(req.URL().Path, "/_ah/") { req.User = &ApiUser{ token: &models.ApiToken{ Token: "x-appengine-ah", Description: "Dummy API Token (_ah user)", CreatedAt: time.Now(), }, lastLogin: time.Now(), } return true } return false }
func Redirect(res *wcg.Response, req *wcg.Request) { urlStr := req.Query("u") if urlobj, err := url.Parse(urlStr); err == nil && validateUrl(urlobj) { // TODO: Check blacklist res.Redirect(urlStr, 302) return } res.TemplatesWithStatus( 404, nil, "404.html", "header.html", "footer.html", ) return }
func cronAuthHandler(res *wcg.Response, req *wcg.Request) bool { cron := req.Header("X-Appengine-Cron") if cron == "true" { req.User = &ApiUser{ token: &models.ApiToken{ Token: "x-appengine-cron", Description: "Dummy API Token (cron user)", CreatedAt: time.Now(), }, lastLogin: time.Now(), } return true } return false }
func apiTokenAuthHandler(res *wcg.Response, req *wcg.Request) bool { token := req.Header("X-SPEEDLAND-API-Token") if token != "" { // API Access d := NewApiTokenDriver(NewAppContextFromRequest(req)) user, err := d.ApiUser(token) if err != nil || user == nil { req.Logger.Warn("API Token(%q) login failed: %v", token, err) } else { req.User = user return true } } return false }
func showBlogHandler(res *wcg.Response, req *wcg.Request) { blog, posts, err := fetchBlog(res, req, true) if err != nil { return } res.SetLocal("Og", &supports.Og{Title: blog.Title, Type: "blog", Url: wcg.AbsoluteUrl(req, req.URL().Path), Description: blog.Description, SiteName: AppConfig.SiteTitle, }) res.SetLocal("blog", blog) res.SetLocal("is_owner", blog.OwnerId == req.User.Id()) res.SetLocal("posts", posts) res.SetLocal("js", "/static/js/blog.js") res.Templates("blog.html", "header.html", "footer.html", "parts/post_part.html") }
func deleteBlogHandler(res *wcg.Response, req *wcg.Request) { driver := models.NewBlogDriver(gae.NewContext(req), req.Logger) err := driver.DeleteBlog(req.Param("blog_id"), req.User.Id()) if err != nil { if supports.IsValidationError(err) { res.WriteJsonWithStatus(400, nil, err) } else if err == models.ErrBlogNotOwned { res.WriteJsonWithStatus(403, nil, no_permission) } else if err == models.ErrBlogNotFound { res.WriteJsonWithStatus(404, nil, not_found) } else { res.RenderInternalError(err.Error()) } return } res.WriteJsonWithStatus(200, nil, ok) }
func (p *Page) _processRequest(res *wcg.Response, req *wcg.Request) { // instance of Page pi := &Page{} pi.App = p.App pi.Title = p.Title pi.Path = p.Path pi.assetPath = p.assetPath if p.templates != nil { pi.templates = make([]string, len(p.templates)) for i := range p.templates { pi.templates[i] = p.templates[i] } } pi.Ogp("site_name", "SPEEDLAND Project") // pre process to update page attributes if p.handler != nil { p.handler(res, req, pi) if res.IsClosed() { return } } // automatically set ogp attributes if not set. if _, ok := pi.ogp["title"]; !ok { pi.Ogp("title", fmt.Sprintf("%s: %s", pi.App.Title, pi.Title)) } if _, ok := pi.ogp["url"]; !ok { pi.Ogp("url", wcg.AbsoluteUrl(req, req.URL().RequestURI())) } // set default OGP from app settings. for k, v := range pi.App.DefaultOgp { pi.Ogp(k, v) } res.SetLocal("Page", pi) res.SetLocal("Ogp", pi.ogp) res.SetLocal("Request", req) res.SetLocal("TrackingCode", TrackingCode) res.SetLocal("__JsBundle__", pi.GetAssetPath()) res.SetLocal("__APP_COMMIT", APP_COMMIT) res.SetLocal("__APP_TIMESTAMP", APP_TIMESTAMP) template_paths := []string{"./header.html", "./footer.html"} res.Templates(append(pi.GetTemplates(), template_paths...)...) }
func showPostHandler(res *wcg.Response, req *wcg.Request) { blog, _, err := fetchBlog(res, req, false) if err != nil { return } post, err := fetchPost(res, req, blog) if err != nil { return } res.SetLocal("Og", &supports.Og{Title: post.Title, Type: "article", Url: wcg.AbsoluteUrl(req, req.URL().Path), SiteName: blog.Title, Description: wcg.Shorten(post.Content, 80), }) res.SetLocal("blog", blog) res.SetLocal("post", post) res.SetLocal("is_owner", post.OwnerId == req.User.Id()) res.SetLocal("js", "/static/js/post.js") res.Templates("post.html", "header.html", "footer.html", "parts/post_part.html") }
func NewService(req *wcg.Request) (*bigquery.Service, error) { var ctx appengine.Context tmp := req.Local("__gaetest__context") if tmp != nil { ctx = tmp.(appengine.Context) } else { ctx = appengine.NewContext(req.HttpRequest()) } client, err := serviceaccount.NewClient(ctx, bigquery.BigqueryScope) if err != nil { return nil, err } svc, err := bigquery.New(client) if err != nil { return nil, err } return svc, nil }
func updatePostHandler(res *wcg.Response, req *wcg.Request) { blog, _, err := fetchBlogForUpdate(res, req, false) if err != nil { return } post, err := fetchPostForUpdate(req, res, blog) if err != nil { return } post.Title = req.Form("title") post.Content = req.Form("content") post.IsDraft = req.Form("is_draft") == "true" post.IsNew = false post.PostDate, err = time.Parse(wcg.FormDateFormat, req.Form("post_date")) post.Tags = strings.Split(req.Form("tags"), ",") for i, v := range post.Tags { post.Tags[i] = strings.TrimSpace(v) } if err != nil { res.WriteHeader(400) res.WriteString("Invalid date format.") res.End() } driver := models.NewPostDriver(gae.NewContext(req), req.Logger) if AppConfig.GithubMarkdown { driver.HttpClient = gae.NewHttpClient(req) } err = driver.SavePost(post) if err != nil { if supports.IsValidationError(err) { res.WriteJsonWithStatus(400, nil, err) } else { res.RenderInternalError(err.Error()) } return } req.Logger.Info("A post is created at %s.", post.Id) res.WriteJsonWithStatus(200, nil, ok) }
func historyInsights(res *wcg.Response, req *wcg.Request, app *App) { var appCtx = lib.NewAppContextFromRequest(req) member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } var insights amebloHistoryInsights mckey := fmt.Sprintf(MC_KEY_HISTORY, app.Key, member.Name) dent := NewAmebloEntryDriver(appCtx) dref := NewAmebloRefDriver(appCtx) mc := appCtx.NewMemcacheDriver() err := mc.CachedObject(mckey, &insights, func() (interface{}, error) { return getAmebloHistoryInsights(member, dent, dref) }, req.Query("force") == "1") if err != nil { lib.Error(res, req, err) return } res.WriteJson(insights) }
func fetchBlog(res *wcg.Response, req *wcg.Request, includePosts bool) (*models.Blog, *supports.Page, error) { // default query for posts. id := req.Param("blog_id") driver := models.NewBlogDriver(gae.NewContext(req), req.Logger) blog, query, err := driver.PostQuery(id) if err != nil { if err == models.ErrBlogNotFound { res.WriteHeader(404) res.WriteString("Not found") res.End() return nil, nil, err } res.RenderInternalError(err.Error()) return nil, nil, err } if !includePosts { return blog, supports.EmptyPage, nil } query = query.Filter("IsNew =", false).Filter("IsDraft =", false).Order("-PostDate").Order("-UpdatedAt") per_page := wcg.ParseInt(req.Query("num"), AppConfig.DefaultPostsFetched, 0, AppConfig.MaxPostsFetched) current := wcg.ParseInt(req.Query("p"), 0, 0, wcg.ParseIntMax) page, err := supports.NewPage(current, per_page, query) if err != nil { res.RenderInternalError("Post pagination error: %v", err) return nil, nil, err } return blog, page, nil }
func listTvChannels(res *wcg.Response, req *wcg.Request) ([]*tv.TvChannel, error) { var list []*tv.TvChannel app := lib.GetCurrentApp(req) ctx := gae.NewContext(req) d := NewTvChannelDriver(app.Key, ctx, req.Logger) mc := memcache.NewDriver(ctx, req.Logger) err := mc.CachedObject(MC_KEY_CHANNELS, &list, func() (interface{}, error) { return d.AllAsList() }, req.Query("force") == "1") if err != nil { return nil, err } else { if len(list) == 0 { req.Logger.Warn("No channel is defined. Reset the configuraiton.") d.AddChannelList(defaultChannels) mc.Delete(MC_KEY_CHANNELS) mc.Set(MC_KEY_CHANNELS, defaultChannels) res.WriteJson(defaultChannels) return defaultChannels, nil } else { return list, nil } } }
func queryPosts(res *wcg.Response, req *wcg.Request, per_page int) (*postQueryResult, error) { var list []blog.Post var basePath = req.HttpRequest().URL.Path is_admin := (lib.GetUserKind(req) == lib.Admin) && (req.Query("is_admin") == "true") if per_page == 0 { per_page = wcg.ParseInt(req.Query("n"), 5, 0, 20) // default 5, max 20 } page := wcg.ParseInt(req.Query("page"), 0, 0, wcg.ParseIntMax) q := NewPostDriver(lib.NewAppContextFromRequest(req)).NewQuery() q = q.Order("-PublishAt").Order("-CreatedAt") if !is_admin { q = q.Filter("PublishAt <=", time.Now()).Filter("IsDraft =", false).Filter("IsHidden =", false) } _, err := q.Offset(page * per_page).Limit(per_page).GetAll(&list) if err != nil { return nil, err } if list == nil { list = make([]blog.Post, 0) } p := &postQueryResult{ Posts: list, } // prev url if page > 0 { p.Previous = fmt.Sprintf("%s?page=%d&n=%d", basePath, page-1, per_page) if is_admin { p.Previous = fmt.Sprintf("%s&is_admin=true", p.Previous) } } // next url if len(list) == per_page { p.Next = fmt.Sprintf("%s?page=%d&n=%d", basePath, page+1, per_page) if is_admin { p.Next = fmt.Sprintf("%s&is_admin=true", p.Next) } } return p, nil }
func createBlogHandler(res *wcg.Response, req *wcg.Request) { driver := models.NewBlogDriver(gae.NewContext(req), req.Logger) blog, err := driver.CreateBlog( req.Form("path"), req.Form("title"), req.Form("description"), req.User.Id(), ) if err != nil { if err == models.ErrBlogAlreadyExists { res.WriteJsonWithStatus(409, nil, already_taken) } else if supports.IsValidationError(err) { res.WriteJsonWithStatus(400, nil, err) } else { res.RenderInternalError(err.Error()) } return } res.WriteJsonWithStatus(201, map[string]string{ "location": wcg.AbsoluteUrl(req, "/"+blog.Id), }, ok) }
func authorizedHandler(res *wcg.Response, req *wcg.Request) { req.Logger.Info("Authorized a user: '******' from %s", req.User.Id(), req.User.DisplayName(), req.RemoteAddr()) authRedirect(res, req) }
func updateShowAttributes(req *wcg.Request, s *event.Show) *event.Show { s.OpenAt, _ = util.ParseDateTime(req.Form("open_at")) s.StartAt, _ = util.ParseDateTime(req.Form("start_at")) s.Latitude, _ = strconv.ParseFloat(req.Form("latitude"), 64) s.Longitude, _ = strconv.ParseFloat(req.Form("longitude"), 64) s.VenueId = req.Form("venue_id") s.VenueName = req.Form("venue_name") s.PiaLink = req.Form("pia_link") s.YAKeyword = req.Form("ya_keyword") return s }