func reindexHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
reindexResponse := make(map[string]interface{})
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
switch r.Method {
case "POST":
if !opUser.IsAdmin() {
jsonErrorReport(w, r, "You are not allowed to perform that action.", http.StatusForbidden)
return
}
reindexAll()
reindexResponse["reindex"] = "OK"
default:
jsonErrorReport(w, r, "Method not allowed. If you're trying to do something with a data bag named 'reindex', it's not going to work I'm afraid.", http.StatusMethodNotAllowed)
return
}
enc := json.NewEncoder(w)
if err := enc.Encode(&reindexResponse); err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError)
}
}
// CheckHeader checks the signed headers sent by the client against the expecte
// result assembled from the request headers to verify their authorization.
func CheckHeader(userID string, r *http.Request) util.Gerror {
user, err := actor.GetReqUser(userID)
if err != nil {
gerr := util.Errorf("Failed to authenticate as '%s'. Ensure that your node_name and client key are correct.", userID)
gerr.SetStatus(http.StatusUnauthorized)
return gerr
}
contentHash := r.Header.Get("X-OPS-CONTENT-HASH")
if contentHash == "" {
gerr := util.Errorf("no content hash provided")
gerr.SetStatus(http.StatusBadRequest)
return gerr
}
authTimestamp := r.Header.Get("x-ops-timestamp")
if authTimestamp == "" {
gerr := util.Errorf("no timestamp header provided")
gerr.SetStatus(http.StatusBadRequest)
return gerr
}
// check the time stamp w/ allowed slew
tok, terr := checkTimeStamp(authTimestamp, config.Config.TimeSlewDur)
if !tok {
return terr
}
// Eventually this may be put to some sort of use, but for now just
// make sure that it's there. Presumably eventually it would be used to
// use algorithms other than sha1 for hashing the body, or using a
// different version of the header signing algorithm.
xopssign := r.Header.Get("x-ops-sign")
var apiVer string
if xopssign == "" {
gerr := util.Errorf("missing X-Ops-Sign header")
return gerr
}
re := regexp.MustCompile(`version=(\d+\.\d+)`)
shaRe := regexp.MustCompile(`algorithm=(\w+)`)
if verChk := re.FindStringSubmatch(xopssign); verChk != nil {
apiVer = verChk[1]
if apiVer != "1.0" && apiVer != "1.1" && apiVer != "1.2" {
gerr := util.Errorf("Bad version number '%s' in X-Ops-Header", apiVer)
return gerr
}
} else {
gerr := util.Errorf("malformed version in X-Ops-Header")
return gerr
}
// if algorithm is missing, it uses sha1. Of course, no other
// hashing algorithm is supported yet...
if shaChk := shaRe.FindStringSubmatch(xopssign); shaChk != nil {
if shaChk[1] != "sha1" {
gerr := util.Errorf("Unsupported hashing algorithm '%s' specified in X-Ops-Header", shaChk[1])
return gerr
}
}
chkHash, chkerr := calcBodyHash(r)
if chkerr != nil {
return chkerr
}
if chkHash != contentHash {
gerr := util.Errorf("Content hash did not match hash of request body")
gerr.SetStatus(http.StatusUnauthorized)
return gerr
}
signedHeaders, sherr := assembleSignedHeader(r)
if sherr != nil {
return sherr
}
headToCheck := assembleHeaderToCheck(r, chkHash, apiVer)
if apiVer == "1.2" {
chkerr = checkAuth12Headers(user, r, headToCheck, signedHeaders)
} else {
chkerr = checkAuthHeaders(user, r, headToCheck, signedHeaders)
}
if chkerr != nil {
chkerr.SetStatus(http.StatusUnauthorized)
return chkerr
}
return nil
}
func dataHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
pathArray := splitPath(r.URL.Path)
dbResponse := make(map[string]interface{})
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
if len(pathArray) == 1 {
/* Either a list of data bags, or a POST to create a new one */
switch r.Method {
case "GET":
if opUser.IsValidator() {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
/* The list */
dbList := databag.GetList()
for _, k := range dbList {
dbResponse[k] = util.CustomURL(fmt.Sprintf("/data/%s", k))
}
case "POST":
if !opUser.IsAdmin() {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
dbData, jerr := parseObjJSON(r.Body)
if jerr != nil {
jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest)
return
}
/* check that the name exists */
switch t := dbData["name"].(type) {
case string:
if t == "" {
jsonErrorReport(w, r, "Field 'name' missing", http.StatusBadRequest)
return
}
default:
jsonErrorReport(w, r, "Field 'name' missing", http.StatusBadRequest)
return
}
chefDbag, _ := databag.Get(dbData["name"].(string))
if chefDbag != nil {
httperr := fmt.Errorf("Data bag %s already exists.", dbData["name"].(string))
jsonErrorReport(w, r, httperr.Error(), http.StatusConflict)
return
}
chefDbag, nerr := databag.New(dbData["name"].(string))
if nerr != nil {
jsonErrorReport(w, r, nerr.Error(), nerr.Status())
return
}
serr := chefDbag.Save()
if serr != nil {
jsonErrorReport(w, r, serr.Error(), http.StatusInternalServerError)
return
}
if lerr := loginfo.LogEvent(opUser, chefDbag, "create"); lerr != nil {
jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError)
return
}
dbResponse["uri"] = util.ObjURL(chefDbag)
w.WriteHeader(http.StatusCreated)
default:
/* The chef-pedant spec wants this response for
* some reason. Mix it up, I guess. */
w.Header().Set("Allow", "GET, POST")
jsonErrorReport(w, r, "GET, POST", http.StatusMethodNotAllowed)
return
}
} else {
dbName := pathArray[1]
/* chef-pedant is unhappy about not reporting the HTTP status
* as 404 by fetching the data bag before we see if the method
* is allowed, so do a quick check for that here. */
if (len(pathArray) == 2 && r.Method == "PUT") || (len(pathArray) == 3 && r.Method == "POST") {
var allowed string
if len(pathArray) == 2 {
allowed = "GET, POST, DELETE"
} else {
allowed = "GET, PUT, DELETE"
}
w.Header().Set("Allow", allowed)
jsonErrorReport(w, r, "Method not allowed", http.StatusMethodNotAllowed)
return
}
if opUser.IsValidator() || (!opUser.IsAdmin() && r.Method != "GET") {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
chefDbag, err := databag.Get(dbName)
if err != nil {
var errMsg string
status := err.Status()
//.........这里部分代码省略.........
func reportHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
protocolVersion := r.Header.Get("X-Ops-Reporting-Protocol-Version")
if protocolVersion == "" {
// try a param (makes working with webui easier)
form, e := url.ParseQuery(r.URL.RawQuery)
if e != nil {
jsonErrorReport(w, r, e.Error(), http.StatusBadRequest)
return
}
if p, f := form["protocol-version"]; f {
if len(p) > 0 {
protocolVersion = p[0]
}
}
}
// someday there may be other protocol versions
if protocolVersion != "0.1.0" {
jsonErrorReport(w, r, "Unsupported reporting protocol version", http.StatusNotFound)
return
}
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
// TODO: some params for time ranges exist and need to be handled
// properly
pathArray := splitPath(r.URL.Path)
pathArrayLen := len(pathArray)
reportResponse := make(map[string]interface{})
switch r.Method {
case "GET":
// Making an informed guess that admin rights are needed
// to see the node run reports
r.ParseForm()
var rows int
var from, until time.Time
var status string
if fr, found := r.Form["rows"]; found {
if len(fr) < 0 {
jsonErrorReport(w, r, "invalid rows", http.StatusBadRequest)
return
}
var err error
rows, err = strconv.Atoi(fr[0])
if err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
return
}
} else {
// default is 10
rows = 10
}
if ff, found := r.Form["from"]; found {
if len(ff) < 0 {
jsonErrorReport(w, r, "invalid from", http.StatusBadRequest)
return
}
fromUnix, err := strconv.ParseInt(ff[0], 10, 64)
if err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
return
}
from = time.Unix(fromUnix, 0)
} else {
from = time.Now().Add(-(time.Duration(24*90) * time.Hour))
}
if fu, found := r.Form["until"]; found {
if len(fu) < 0 {
jsonErrorReport(w, r, "invalid until", http.StatusBadRequest)
return
}
untilUnix, err := strconv.ParseInt(fu[0], 10, 64)
if err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
return
}
until = time.Unix(untilUnix, 0)
} else {
until = time.Now()
}
if st, found := r.Form["status"]; found {
if len(st) < 0 {
jsonErrorReport(w, r, "invalid status", http.StatusBadRequest)
return
}
status = st[0]
if status != "started" && status != "success" && status != "failure" {
jsonErrorReport(w, r, "invalid status given", http.StatusBadRequest)
return
}
}
//.........这里部分代码省略.........
func searchHandler(w http.ResponseWriter, r *http.Request) {
/* ... and we need search to run the environment tests, so here we
* go. */
w.Header().Set("Content-Type", "application/json")
searchResponse := make(map[string]interface{})
pathArray := splitPath(r.URL.Path)
pathArrayLen := len(pathArray)
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
/* set up query params for searching */
var (
paramQuery string
paramsRows int
sortOrder string
start int
)
r.ParseForm()
if q, found := r.Form["q"]; found {
if len(q) < 0 {
jsonErrorReport(w, r, "No query string specified for search", http.StatusBadRequest)
return
}
paramQuery = q[0]
} else if pathArrayLen != 1 {
/* default to "*:*" for a search term */
paramQuery = "*:*"
}
if pr, found := r.Form["rows"]; found {
if len(pr) > 0 {
paramsRows, _ = strconv.Atoi(pr[0])
}
} else {
paramsRows = 1000
}
sortOrder = "id ASC"
if s, found := r.Form["sort"]; found {
if len(s) > 0 {
if s[0] != "" {
sortOrder = s[0]
}
} else {
sortOrder = "id ASC"
}
}
if st, found := r.Form["start"]; found {
if len(st) > 0 {
start, _ = strconv.Atoi(st[0])
}
} else {
start = 0
}
var searcher search.Searcher
if config.Config.PgSearch {
searcher = &search.PostgresSearch{}
} else {
searcher = &search.TrieSearch{}
}
if pathArrayLen == 1 {
/* base end points */
switch r.Method {
case "GET":
if opUser.IsValidator() {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
searchEndpoints := searcher.GetEndpoints()
for _, s := range searchEndpoints {
searchResponse[s] = util.CustomURL(fmt.Sprintf("/search/%s", s))
}
default:
jsonErrorReport(w, r, "Method not allowed", http.StatusMethodNotAllowed)
return
}
} else if pathArrayLen == 2 {
switch r.Method {
case "GET", "POST":
if opUser.IsValidator() {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
var qerr error
paramQuery, qerr = url.QueryUnescape(paramQuery)
if qerr != nil {
jsonErrorReport(w, r, qerr.Error(), http.StatusBadRequest)
return
}
/* start figuring out what comes in POSTS now,
* so the partial search tests don't complain
* anymore. */
var partialData map[string]interface{}
if r.Method == "POST" {
var perr error
partialData, perr = parseObjJSON(r.Body)
//.........这里部分代码省略.........
func reindexHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
reindexResponse := make(map[string]interface{})
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
switch r.Method {
case "POST":
if !opUser.IsAdmin() {
jsonErrorReport(w, r, "You are not allowed to perform that action.", http.StatusForbidden)
return
}
reindexObjs := make([]indexer.Indexable, 0, 100)
// We clear the index, *then* do the fetch because if
// something comes in between the time we fetch the
// objects to reindex and when it gets done, they'll
// just be added naturally
indexer.ClearIndex()
for _, v := range client.AllClients() {
reindexObjs = append(reindexObjs, v)
}
for _, v := range node.AllNodes() {
reindexObjs = append(reindexObjs, v)
}
for _, v := range role.AllRoles() {
reindexObjs = append(reindexObjs, v)
}
for _, v := range environment.AllEnvironments() {
reindexObjs = append(reindexObjs, v)
}
defaultEnv, _ := environment.Get("_default")
reindexObjs = append(reindexObjs, defaultEnv)
// data bags have to be done separately
dbags := databag.GetList()
for _, db := range dbags {
dbag, err := databag.Get(db)
if err != nil {
continue
}
dbis := make([]indexer.Indexable, dbag.NumDBItems())
i := 0
allDBItems, derr := dbag.AllDBItems()
if derr != nil {
logger.Errorf(derr.Error())
continue
}
for _, k := range allDBItems {
n := k
dbis[i] = n
i++
}
reindexObjs = append(reindexObjs, dbis...)
}
indexer.ReIndex(reindexObjs)
reindexResponse["reindex"] = "OK"
default:
jsonErrorReport(w, r, "Method not allowed. If you're trying to do something with a data bag named 'reindex', it's not going to work I'm afraid.", http.StatusMethodNotAllowed)
return
}
enc := json.NewEncoder(w)
if err := enc.Encode(&reindexResponse); err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError)
}
}
开发者ID:ranjib,项目名称:goiardi,代码行数:67,代码来源:search.go
示例10: cookbookHandler
func cookbookHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
pathArray := splitPath(r.URL.Path)
cookbookResponse := make(map[string]interface{})
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
jsonErrorReport(w, r, oerr.Error(), oerr.Status())
return
}
var numResults string
r.ParseForm()
if nrs, found := r.Form["num_versions"]; found {
if len(nrs) < 0 {
jsonErrorReport(w, r, "invalid num_versions", http.StatusBadRequest)
return
}
numResults = nrs[0]
err := util.ValidateNumVersions(numResults)
if err != nil {
jsonErrorReport(w, r, err.Error(), err.Status())
return
}
}
force := ""
if f, fok := r.Form["force"]; fok {
if len(f) > 0 {
force = f[0]
}
}
pathArrayLen := len(pathArray)
/* 1 and 2 length path arrays only support GET */
if pathArrayLen < 3 && r.Method != "GET" {
jsonErrorReport(w, r, "Bad request.", http.StatusMethodNotAllowed)
return
} else if pathArrayLen < 3 && opUser.IsValidator() {
jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
return
}
/* chef-pedant is happier when checking if a validator can do something
* surprisingly late in the game. It wants the perm checks to be
* checked after the method for the end point is checked out as
* something it's going to handle, so, for instance, issuing a DELETE
* against an endpoint where that isn't allowed should respond with a
* 405, rather than a 403, which also makes sense in areas where
* validators shouldn't be able to do anything. *shrugs*
*/
if pathArrayLen == 1 || (pathArrayLen == 2 && pathArray[1] == "") {
/* list all cookbooks */
cookbookResponse = cookbook.CookbookLister(numResults)
} else if pathArrayLen == 2 {
/* info about a cookbook and all its versions */
cookbookName := pathArray[1]
/* Undocumented behavior - a cookbook name of _latest gets a
* list of the latest versions of all the cookbooks, and _recipe
* gets the recipes of the latest cookbooks. */
if cookbookName == "_latest" {
cookbookResponse = cookbook.CookbookLatest()
} else if cookbookName == "_recipes" {
rlist, nerr := cookbook.CookbookRecipes()
if nerr != nil {
jsonErrorReport(w, r, nerr.Error(), nerr.Status())
return
}
enc := json.NewEncoder(w)
if err := enc.Encode(&rlist); err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError)
}
return
} else {
cb, err := cookbook.Get(cookbookName)
if err != nil {
jsonErrorReport(w, r, err.Error(), http.StatusNotFound)
return
}
/* Strange thing here. The API docs say if num_versions
* is not specified to return one cookbook, yet the
* spec indicates that if it's not set that all
* cookbooks should be returned. Most places *except
* here* that's the case, so it can't be changed in
* infoHashBase. Explicitly set numResults to all
* here. */
if numResults == "" {
numResults = "all"
}
cookbookResponse[cookbookName] = cb.InfoHash(numResults)
}
} else if pathArrayLen == 3 {
/* get information about or manipulate a specific cookbook
* version */
cookbookName := pathArray[1]
var cookbookVersion string
var vererr util.Gerror
opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
if oerr != nil {
//.........这里部分代码省略.........
请发表评论