예제 #1
0
func ParseForm(configure func(*validators.FormValidator)) server.Handler {
	// it's ok to set nil as configure to parse form without validation.
	var v *validators.FormValidator
	if configure != nil {
		v = validators.NewFormValidator()
		configure(v)
	}
	return server.Handler(
		func(req *wcg.Request) response.Response {
			if m := req.Method(); m != "POST" && m != "PUT" {
				return nil
			}
			if req.Header("content-type") != "application/x-www-form-urlencoded" {
				req.Logger.Debugf("Skip FormValidation since the requested content is not a form")
				return nil
			}
			err := req.HTTPRequest().ParseForm()
			if err == nil {
				req.Logger.Debugf("Request Form: %v", req.HTTPRequest().Form)
			} else {
				req.Logger.Warnf("ParseForm failed in FormValidaiton process. Triggered ValidationError: %v", err)
				return response.BadRequest(req, err)
			}

			if v == nil {
				req.Logger.Debugf("Skip FormValidation since no validator is defined.")
				return nil
			}
			if err := v.Eval(req.HTTPRequest().Form); err != nil {
				return response.BadRequest(req, err)
			}
			return nil
		})
}
예제 #2
0
파일: entity.go 프로젝트: speedland/service
func EntityPost(post *entities.Put) server.Handler {
	return server.Handler(
		func(req *wcg.Request) response.Response {
			ent, err := post.Kind().CreateEntityFromForm(req.HTTPRequest().Form)
			if err != nil { // ParseError
				req.Logger.Warnf("You should use ParseForm middleware to avoid the error in EntityPost: %v", err)
				return response.BadRequest(req, ErrInvalidFormParameters)
			}
			_, ent_ := post.MustUpdate(req, ent)
			return response.NewJSONResponseWithStatus(ent_, 201)
		})
}
예제 #3
0
func ValidateQuery(configure func(*validators.FormValidator)) server.Handler {
	if configure == nil {
		panic(fmt.Errorf("You must pass configure function on ValidateQuery"))
	}
	v := validators.NewFormValidator()
	configure(v)
	return server.Handler(
		func(req *wcg.Request) response.Response {
			if err := v.Eval(req.URL().Query()); err != nil {
				return response.BadRequest(req, err)
			}
			return nil
		})
}
예제 #4
0
파일: entity.go 프로젝트: speedland/service
func processEntityPut(req *wcg.Request, put *entities.Put, keyParams string, create bool) response.Response {
	key := req.Param(keyParams)
	_, ent := put.Kind().Get().Key(key).UseDefaultIfNil(create).MustOne(req)
	if ent == nil {
		return response.APINotFound
	}
	if req.HTTPRequest().Form == nil {
		req.Logger.Warnf("You should use ParseForm middleware to avoid the error in EntityPut|EntityPutOrCreate")
		return response.InternalServerError(req, ErrInvalidFormParameters).(response.Response)
	}
	err := put.Kind().UpdateEntityFromForm(ent, req.HTTPRequest().Form)
	if err != nil {
		return response.BadRequest(req, ErrInvalidFormParameters)
	}
	_, ent_ := put.Key(key).MustUpdate(req, ent)
	return response.NewJSONResponseWithStatus(ent_, 200)
}
예제 #5
0
파일: api.go 프로젝트: speedland/service
	"lib/server/configs"
	"lib/server/response"
	"lib/wcg"
)

// SetupHandler is a server.Handler to respond setup HTTP call from a Facebook server
var SetupHandler = server.Handler(func(req *wcg.Request) response.Response {
	token := configs.GetValue(req, "facebook_messenger_verify_token")
	if token == "" {
		return response.NotFound(req)
	}
	if req.Query("hub.verify_token") != token {
		return response.BadRequest(
			req,
			fmt.Errorf(
				"token mismatch: hub.verify_token(%q) != facebook_messenger_verify_token(%q)",
				req.Query("hub.verify_token"), token,
			),
		)
	}
	return response.NewTextResponse(req.Query("hub.challenge"))
})

// WebhookHandler is a server.Handler to respond setup HTTP call from a Facebook server
var WebHookHandler = server.Handler(func(req *wcg.Request) response.Response {
	messages, perr := parseMessage(req.HTTPRequest().Body)
	if perr != nil {
		req.Logger.Warnf("Server could not parse incomming messenger hook message: %s", perr)
		return response.NewJSONResponse(true)
	}
	for _, msg := range messages {
예제 #6
0
func setupAPIOAuth2(app *server.App) {
	var API = app.API()

	API.GET("/oauth2/clients/",
		middleware.EntityAll(entities.OAuth2ClientSettings.Query()))

	API.GET("/oauth2/clients/:key.json",
		middleware.EntityGet(entities.OAuth2ClientSettings.Get().Cache(true), "key"))

	// Create an oauth2.Config object into session and redirect to the oauth2 endpoint.
	// /admin/oauth2/callback.html will finally authorize the callback code and store the oauth2.Config into datastore.
	API.POST("/oauth2/clients/",
		middleware.ParseForm(func(v *validators.FormValidator) {
			v.Field("key").Required()
			v.Field("client_id").Required()
			v.Field("client_secret").Required()
			v.Field("auth_url").Required()
			v.Field("token_url").Required()
		}),
		server.Handler(func(req *wcg.Request) response.Response {
			cfg := &oauth2.Config{
				ClientID:     req.Form("client_id"),
				ClientSecret: req.Form("client_secret"),
				Endpoint: oauth2.Endpoint{
					AuthURL:  req.Form("auth_url"),
					TokenURL: req.Form("token_url"),
				},
				Scopes: strings.Split(req.Form("scopes"), ","),
				RedirectURL: wcg.AbsoluteURL(
					req,
					fmt.Sprintf("/api/admin/oauth2/callback/?oauth2_key=%s", req.Form("key")),
				),
			}
			data := wcg.DataBag{}
			data.Set("key", req.Form("key"))
			data.Set("client_id", cfg.ClientID)
			data.Set("client_secret", cfg.ClientSecret)
			data.Set("auth_url", cfg.Endpoint.AuthURL)
			data.Set("token_url", cfg.Endpoint.TokenURL)
			data.Set("scopes", req.Form("scopes"))
			data.Set("redirect_url", cfg.RedirectURL)
			req.Session.SetData(
				fmt.Sprintf("admin.oauth2_%s", req.Form("key")),
				data,
			)
			return response.NewRedirect(cfg.AuthCodeURL("state", oauth2.AccessTypeOffline), response.RedirectSeeOther)
		}))

	API.DELETE("/oauth2/clients/:client_id.json",
		middleware.EntityDelete(entities.OAuth2ClientSettings.Delete(), "client_id"))

	API.GET("/oauth2/callback/",
		server.Handler(func(req *wcg.Request) response.Response {
			key := req.Query("oauth2_key")
			code := req.Query("code")
			data, ok := req.Session.GetData(fmt.Sprintf("admin.oauth2_%s", key))
			if !ok {
				return response.NotFound(req)
			}
			scopes, _ := data.Get("scopes")
			cfg := &oauth2.Config{}
			cfg.ClientID, _ = data.Get("client_id")
			cfg.ClientSecret, _ = data.Get("client_secret")
			cfg.Endpoint.AuthURL, _ = data.Get("auth_url")
			cfg.Endpoint.TokenURL, _ = data.Get("token_url")
			cfg.Scopes = strings.Split(scopes, ",")
			cfg.RedirectURL, _ = data.Get("redirect_url")
			token, err := cfg.Exchange(gae.NewContext(req), code)
			if err != nil {

				return response.BadRequest(req, err)
			}
			settings := models.NewOAuth2ClientSettings(cfg, token)
			settings.Key = key
			entities.OAuth2ClientSettings.Put().Key(key).MustUpdate(req, settings)
			return response.NewRedirect("/admin/oauth2/", response.RedirectSeeOther)
		}))

}
예제 #7
0
func setupAPIIEPGRecords(app *server.App) {
	var API = app.API()

	API.GET("/iepg/records/",
		middleware.EntityQuery(recentRecordsQuery()))

	API.GET("/iepg/records/:id.json",
		middleware.EntityGet(IEPG.Get().Cache(true), "id"))

	API.POST("/iepg/records/",
		middleware.Gate("family"),
		middleware.ParseForm(func(v *validators.FormValidator) {
			v.Field("program_title").Required()
			v.Field("start_at").Required()
			v.Field("end_at").Required()
			v.Field("category").Required()
			v.Field("cid").Required()
			v.Field("sid").Required()
		}),
		middleware.EntityPost(
			IEPG.Put().
				SetField("Source", pt.IEPGSourceUser).
				Cache(_CacheRecentIEPGRecords),
		),
	)

	API.PUT("/iepg/records/:id.json",
		middleware.Gate("family"),
		middleware.ParseForm(func(v *validators.FormValidator) {
			v.Field("program_title").Required()
			v.Field("start_at").Required()
			v.Field("end_at").Required()
			v.Field("category").Required()
			v.Field("cid").Required()
			v.Field("sid").Required()
		}),
		requireIEPGOwner("id"),
		middleware.EntityPut(
			IEPG.Put().
				SetField("Source", pt.IEPGSourceUser).
				Cache(_CacheRecentIEPGRecords),
			"id",
		),
	)

	API.POST("/iepg/records/:id/notification.json",
		middleware.Gate("family"),
		getIEPG("id", func(req *wcg.Request, iepg *pt.IEPG) response.Response {
			var msg string
			var configs []pt.MessengerNotification
			var err error
			t := req.Form("type")
			switch t {
			case "start":
				msg = fmt.Sprintf("[%s] 録画を開始しました。", iepg.ProgramTitle)
				configs, err = getMessengerNotificationOptInUsers(req, "OnStart")
				break
			case "end":
				msg = fmt.Sprintf("[%s] 録画を終了しました。", iepg.ProgramTitle)
				configs, err = getMessengerNotificationOptInUsers(req, "OnEnd")
				break
			default:
				return response.BadRequest(req, fmt.Errorf("`type` should be specified and must be one of 'start', 'end' (actual=%s)", t))
			}
			if err != nil {
				return response.InternalServerError(req, err)
			}
			if req.Form("message") != "" {
				msg = fmt.Sprintf("%s\n%s", msg, req.Form("message"))
			}

			for _, cfg := range configs {
				client := messenger.NewMessengerClient(req)
				client.UserID = cfg.UserID
				err = client.SendText(msg)
				if err != nil {
					req.Logger.Warnf("Failed to send a messenger message: %v", err)
				}
			}
			return response.NewJSONResponse(true)
		}),
	)

	API.DELETE("/iepg/records/:id.json",
		middleware.Gate("family"),
		requireIEPGOwner("id"),
		middleware.EntityDelete(IEPG.Delete().Cache(_CacheRecentIEPGRecords), "id"))

	// optin or optout for auto collected IEPGs
	API.PUT("/iepg/records/:id/opt-in/",
		middleware.Gate("family"),
		getIEPG("id", func(req *wcg.Request, iepg *pt.IEPG) response.Response {
			err := iepg.SetOptIn(req.Form("opt_in") == "1" || req.Form("opt_in") == "true")
			if err != nil {
				return response.BadRequest(req, fmt.Errorf("Could not configure opt-in field on the user created IEPG"))
			}
			IEPG.Put().Key(req.Param("id")).Cache(_CacheRecentIEPGRecords).MustUpdate(req, iepg)
			return response.NewJSONResponse(map[string]bool{
				"ok":      true,
				"opt_in":  iepg.OptIn,
				"opt_out": iepg.OptOut,
			})
		}),
	)
}
예제 #8
0
func setupAPIStats(app *server.App) {
	var API = app.API()

	API.GET("/stats/servers/",
		middleware.EntityAll(Server.Query()))

	API.GET("/stats/nasdisks/",
		middleware.EntityAll(NASDisk.Query()))

	API.GET("/stats/servers/:server/:stats/",
		server.Handler(
			func(req *wcg.Request) response.Response {
				key, _ := Server.Get().Key(req.Param("server")).Cache(true).MustOne(req)
				if key == nil {
					req.Logger.Debugf("server %q is not found.", req.Param("server"))
					return response.NotFound(req)
				}
				var kind *entities.Kind
				switch req.Param("stats") {
				case "system":
					kind = SystemStats
					break
				case "cpu":
					kind = CPUStats
					break
				case "memory":
					kind = MemoryStats
					break
				case "disk":
					kind = DiskStats
					break
				case "filesystem":
					kind = FileSystemStats
					break
				case "network":
					kind = NetworkStats
					break
				default:
					req.Logger.Debugf("metric %q is invalid.", req.Param("stats"))
					return response.NotFound(req)
				}
				return execStatsQuery(req, kind.Query().Ancestor(key))
			},
		))

	API.POST("/stats/metrics/",
		middleware.APITokenOnly(),
		server.Handler(
			func(req *wcg.Request) response.Response {
				ent, err := SystemMetric.CreateEntitiesFromJSON(req.HTTPRequest().Body)
				if err != nil {
					return response.BadRequest(req, err)
				}
				collection := home.NewStatsFromMetrics(ent.([]*home.SystemMetric))
				if len(collection) == 0 {
					return response.BadRequest(req, fmt.Errorf("No stats are collected."))
				}
				if collection[0].System.ServerName == "" {
					return response.BadRequest(req, fmt.Errorf("server_name is missing"))
				}
				for _, stats := range collection {
					key := getServerKey(req, stats.System.ServerName)
					id := fmt.Sprintf("%s.%d", key.StringID(), stats.Timestamp.Unix())
					stats.System.ID = id
					stats.CPU.ID = id
					stats.Memory.ID = id
					for _, v := range stats.Disks {
						v.ID = fmt.Sprintf("%s.%s.%d", key.StringID(), v.DeviceName, stats.Timestamp.Unix())
					}
					for _, v := range stats.Networks {
						v.ID = fmt.Sprintf("%s.%s.%d", key.StringID(), v.DeviceName, stats.Timestamp.Unix())
					}
					SystemStats.Put().Parent(key).MustUpdate(req, stats.System)
					CPUStats.Put().Parent(key).MustUpdate(req, stats.CPU)
					MemoryStats.Put().Parent(key).MustUpdate(req, stats.Memory)
					DiskStats.PutMulti().Parent(key).MustUpdate(req, stats.Disks)
					NetworkStats.PutMulti().Parent(key).MustUpdate(req, stats.Networks)
				}
				return response.NewJSONResponse(true)
			},
		))

	API.POST("/stats/filesystem/",
		middleware.APITokenOnly(),
		server.Handler(
			func(req *wcg.Request) response.Response {
				ent, err := FileSystemStats.CreateEntitiesFromJSON(req.HTTPRequest().Body)
				if err != nil {
					return response.BadRequest(req, err)
				}
				filesystems := ent.([]*home.FileSystemStats)
				if filesystems[0].ServerName == "" {
					return response.BadRequest(req, fmt.Errorf("server_name is missing"))
				}
				key := getServerKey(req, filesystems[0].ServerName)
				for _, fs := range filesystems {
					fs.ID = fmt.Sprintf("%s.%s.%d", fs.ServerName, fs.Name, fs.Timestamp.Unix())
				}
				FileSystemStats.PutMulti().Parent(key).MustUpdate(req, filesystems)
				return response.NewJSONResponse(true)
			},
		))

	API.POST("/stats/smart/",
		middleware.APITokenOnly(),
		server.Handler(
			func(req *wcg.Request) response.Response {
				ent, err := SMARTStats.CreateEntitiesFromJSON(req.HTTPRequest().Body)
				if err != nil {
					return response.BadRequest(req, err)
				}
				smartstats := ent.([]*home.SMARTStats)
				if smartstats[0].Serial == "" {
					return response.BadRequest(req, fmt.Errorf("serial is missing"))
				}
				key := getNASDiskKey(req, smartstats[0].Serial)
				for _, smart := range smartstats {
					smart.ID = fmt.Sprintf("%s.%d", smart.Serial, smart.Timestamp.Unix())
				}
				SMARTStats.PutMulti().Parent(key).MustUpdate(req, smartstats)
				return response.NewJSONResponse(true)
			},
		))
}