Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
// 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())
}
Beispiel #4
0
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
	}
}
Beispiel #5
0
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
}
Beispiel #6
0
func GetCurrentApp(req *wcg.Request) *App {
	if app := req.Local(LOCAL_APP_KEY); app != nil {
		return app.(*App)
	} else {
		return nil
	}
}
Beispiel #7
0
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",
	)
}
Beispiel #8
0
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)
}
Beispiel #9
0
// 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),
	})
}
Beispiel #10
0
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)
	}
}
Beispiel #11
0
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
	}
}
Beispiel #12
0
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
}
Beispiel #13
0
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
}
Beispiel #14
0
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
}
Beispiel #15
0
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
}
Beispiel #16
0
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
}
Beispiel #17
0
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
}
Beispiel #18
0
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")
}
Beispiel #19
0
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)
}
Beispiel #20
0
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...)...)
}
Beispiel #21
0
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")
}
Beispiel #22
0
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
}
Beispiel #23
0
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)
}
Beispiel #24
0
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)
}
Beispiel #25
0
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
}
Beispiel #26
0
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
		}
	}
}
Beispiel #27
0
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
}
Beispiel #28
0
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)
}
Beispiel #29
0
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)
}
Beispiel #30
0
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
}