func authClient(clientId, clientSecret string) error { acc, err := db.Search(clientId, "", 1, 0) if err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } if len(acc) == 0 { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } // check the secret salt, secret, err := db.SaltAndSecret(acc[0].Id) if err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } s, err := base64.StdEncoding.DecodeString(secret) if err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } // does it match? if err := bcrypt.CompareHashAndPassword(s, []byte(x+salt+clientSecret)); err != nil { return errors.BadRequest("go.micro.srv.auth", "access_denied") } return nil }
func (r *Rule) Update(ctx context.Context, req *proto.UpdateRequest, rsp *proto.UpdateResponse) error { if req.Rule == nil { return errors.BadRequest("go.micro.srv.router.Rule.Update", "invalid rule") } if len(req.Rule.Id) == 0 { return errors.BadRequest("go.micro.srv.router.Rule.Update", "invalid id") } if len(req.Rule.Service) == 0 { return errors.BadRequest("go.micro.srv.router.Rule.Update", "invalid service") } if len(req.Rule.Version) == 0 { return errors.BadRequest("go.micro.srv.router.Rule.Update", "invalid version") } if req.Rule.Weight < 0 || req.Rule.Weight > 100 { return errors.BadRequest("go.micro.srv.router.Rule.Update", "invalid weight, must be 0 to 100") } if err := rule.Update(req.Rule); err != nil { return errors.InternalServerError("go.micro.srv.router.Rule.Update", err.Error()) } return nil }
func (r *Label) Update(ctx context.Context, req *proto.UpdateRequest, rsp *proto.UpdateResponse) error { if req.Label == nil { return errors.BadRequest("go.micro.srv.router.Label.Update", "invalid label") } if len(req.Label.Id) == 0 { return errors.BadRequest("go.micro.srv.router.Label.Update", "invalid id") } if len(req.Label.Service) == 0 { return errors.BadRequest("go.micro.srv.router.Label.Update", "invalid service") } if len(req.Label.Key) == 0 { return errors.BadRequest("go.micro.srv.router.Label.Update", "invalid key") } if req.Label.Weight < 0 || req.Label.Weight > 100 { return errors.BadRequest("go.micro.srv.router.Label.Update", "invalid weight, must be 0 to 100") } if err := label.Update(req.Label); err != nil { return errors.InternalServerError("go.micro.srv.router.Label.Update", err.Error()) } return nil }
func (o *Oauth2) Revoke(ctx context.Context, req *oauth2.RevokeRequest, rsp *oauth2.RevokeResponse) error { // Who should be allowed to do this? if len(req.RefreshToken) > 0 { token, _, err := db.ReadRefresh(req.RefreshToken) if err != nil { if err == db.ErrNotFound { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } return errors.InternalServerError("go.micro.srv.auth", "server_error") } if err := db.DeleteToken(req.AccessToken); err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } req.AccessToken = token.AccessToken } if len(req.AccessToken) == 0 { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } if err := db.DeleteToken(req.AccessToken); err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } return nil }
// DocRefFieldsExists returns an error if DocRef struct has zero value func DocRefFieldsExists(dr *proto.DocRef) error { if len(dr.Index) <= 0 { return errors.BadRequest("go.micro.srv.elastic", "Index required") } if len(dr.Type) <= 0 { return errors.BadRequest("go.micro.srv.elastic", "Type required") } return nil }
// Query API handler func (es *Elastic) Query(ctx context.Context, req *api.Request, rsp *api.Response) error { var err error var input map[string]interface{} var query []byte // Unmarshal unknown JSON if err = json.Unmarshal([]byte(req.Body), &input); err != nil { return errors.BadRequest("go.micro.api.elastic", err.Error()) } query, err = json.Marshal(input["query"]) srvReq := client.NewRequest( "go.micro.srv.elastic", "Elastic.Query", &elastic.QueryRequest{ Index: fmt.Sprintf("%v", input["index"]), Type: fmt.Sprintf("%v", input["type"]), Query: string(query), }, ) srvRsp := &elastic.SearchResponse{} if err = client.Call(ctx, srvReq, srvRsp); err != nil { return err } rsp.StatusCode = http.StatusOK rsp.Body = srvRsp.Result return nil }
func validateDB(method string, d *mdb.Database) error { if d == nil { return errors.BadRequest("go.micro.srv.db."+method, "invalid database") } if len(d.Name) == 0 { return errors.BadRequest("go.micro.srv.db."+method, "database is blank") } if len(d.Table) == 0 { return errors.BadRequest("go.micro.srv.db."+method, "table is blank") } // TODO: check exists return nil }
func (s *Say) Hello(ctx context.Context, req *api.Request, rsp *api.Response) error { log.Info("Received Say.Hello API request") name, ok := req.Get["name"] if !ok || len(name.Values) == 0 { return errors.BadRequest("go.micro.api.greeter", "Name cannot be blank") } request := client.NewRequest("go.micro.srv.greeter", "Say.Hello", &hello.Request{ Name: strings.Join(name.Values, " "), }) response := &hello.Response{} if err := client.Call(ctx, request, response); err != nil { return err } rsp.StatusCode = 200 b, _ := json.Marshal(map[string]string{ "message": response.Msg, }) rsp.Body = string(b) return nil }
func (r *Router) SelectStream(ctx context.Context, req *proto.SelectRequest, stream proto.Router_SelectStreamStream) error { // TODO: process filters if len(req.Service) == 0 { return errors.BadRequest("go.micro.srv.router.Router.Select", "invalid service name") } t := time.NewTicker(time.Duration(router.DefaultExpiry) * time.Second) defer t.Stop() for { services, err := router.Select(req.Service) if err != nil && err == selector.ErrNotFound { return errors.NotFound("go.micro.srv.router.Router.SelectStream", err.Error()) } else if err != nil { return errors.InternalServerError("go.micro.srv.router.Router.SelectStream", err.Error()) } if err := stream.Send(&proto.SelectResponse{ Services: services, Expires: time.Now().Unix() + int64(router.DefaultExpiry), }); err != nil { return err } <-t.C } return nil }
func (o *Oauth2) Introspect(ctx context.Context, req *oauth2.IntrospectRequest, rsp *oauth2.IntrospectResponse) error { // Who should be allowed to do this? if len(req.AccessToken) == 0 { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } token, _, err := db.ReadToken(req.AccessToken) if err != nil { if err == db.ErrNotFound { rsp.Active = false return nil } return errors.InternalServerError("go.micro.srv.auth", "server_error") } if d := time.Now().Unix() - token.ExpiresAt; d > 0 { rsp.Active = false return nil } rsp.Token = token rsp.Active = true // should we really hand this over? rsp.Token.RefreshToken = "" return nil }
// Update API handler func (es *Elastic) Update(ctx context.Context, req *api.Request, rsp *api.Response) error { var err error var input map[string]interface{} var data []byte // Unmarshal unknown JSON if err = json.Unmarshal([]byte(req.Body), &input); err != nil { return errors.BadRequest("go.micro.api.elastic", err.Error()) } // Marshal unknown JSON (data) data, err = json.Marshal(input["data"]) srvReq := client.NewRequest( "go.micro.srv.elastic", "Elastic.Update", &elastic.UpdateRequest{ Index: fmt.Sprintf("%v", input["index"]), Type: fmt.Sprintf("%v", input["type"]), Id: fmt.Sprintf("%v", input["id"]), Data: string(data), }, ) srvRsp := &elastic.UpdateResponse{} if err = client.Call(ctx, srvReq, srvRsp); err != nil { return err } rsp.StatusCode = http.StatusOK rsp.Body = `{}` return nil }
func (o *Oauth2) Authorize(ctx context.Context, req *oauth2.AuthorizeRequest, rsp *oauth2.AuthorizeResponse) error { // We may actually need to authenticate who can make this request. // How should we do that? switch req.ResponseType { // requesting authorization code case "code": // check client id exists if len(req.ClientId) == 0 { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } // if redirect uri exists and is not tls lets bail if len(req.RedirectUri) > 0 && !strings.HasPrefix(req.RedirectUri, "https://") { return errors.BadRequest("go.micro.srv.auth", "invalid_request") } // use default scope if len(req.Scopes) == 0 { req.Scopes = append(req.Scopes, DefaultScope) } // generate code code := db.Code() // store request; expire in 10 mins if err := db.CreateRequest(code, req); err != nil { return errors.InternalServerError("go.micro.srv.auth", "server_error") } // respond rsp.Code = code rsp.State = req.State // we're done?! // implicit token request case "token": // to be implemented return errors.BadRequest("go.micro.srv.auth", "unsupported_response_type") default: return errors.BadRequest("go.micro.srv.auth", "unsupported_response_type") } return nil }
func Stream(ctx context.Context, rec *event.Record) error { if rec == nil { return errors.BadRequest("go.micro.srv.event.Process", "invalid record") } if len(rec.Id) == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid id") } if len(rec.Type) == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid type") } if rec.Timestamp == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid timestamp") } mtx.RLock() defer mtx.RUnlock() gsubscribers := subs[all] subscribers := subs[rec.Type] // send to subscribers in a go channel go func() { // send to global subscribers for _, sub := range gsubscribers { select { case sub.ch <- rec: case <-time.After(time.Millisecond * 100): } } // send to type subscribers for _, sub := range subscribers { select { case sub.ch <- rec: case <-time.After(time.Millisecond * 100): } } }() return nil }
func (e *Event) Update(ctx context.Context, req *event.UpdateRequest, rsp *event.UpdateResponse) error { if req.Record == nil { return errors.BadRequest("go.micro.srv.event.Update", "invalid record") } if len(req.Record.Id) == 0 { return errors.BadRequest("go.micro.srv.event.Update", "invalid id") } if req.Record.Timestamp == 0 { req.Record.Timestamp = time.Now().Unix() } if err := db.Update(req.Record); err != nil { return errors.InternalServerError("go.micro.srv.event.Update", err.Error()) } return nil }
func (s *Account) Delete(ctx context.Context, req *account.DeleteRequest, rsp *account.DeleteResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.auth.Delete", "invalid id") } if err := db.Delete(req.Id); err != nil { return errors.InternalServerError("go.micro.srv.auth.Delete", err.Error()) } return nil }
func (d *DB) Create(ctx context.Context, req *mdb.CreateRequest, rsp *mdb.CreateResponse) error { if req.Record == nil { return errors.BadRequest("go.micro.srv.db.DB.Create", "invalid record") } if err := validateDB("DB.Create", req.Database); err != nil { return err } if len(req.Record.Id) == 0 { return errors.BadRequest("go.micro.srv.db.DB.Create", "invalid id") } if err := db.Create(req.Database, req.Record); err != nil { return errors.InternalServerError("go.micro.srv.db.DB.Create", err.Error()) } return nil }
func (s *Account) Update(ctx context.Context, req *account.UpdateRequest, rsp *account.UpdateResponse) error { // validate incoming if err := validateAccount(req.Account, "Update"); err != nil { return err } // need an account id for update if len(req.Account.Id) == 0 { return errors.BadRequest("go.micro.srv.auth.Update", "invalid id") } // lookup the record and verify it's the same acc, err := db.Read(req.Account.Id) if err != nil { return errors.InternalServerError("go.micro.srv.auth.Update", err.Error()) } // not the same client id if req.Account.ClientId != acc.ClientId { return errors.BadRequest("go.micro.srv.auth.Update", "invalid client id") } // hash the pass salt := db.Salt() h, err := bcrypt.GenerateFromPassword([]byte(x+salt+req.Account.ClientSecret), 10) if err != nil { return errors.InternalServerError("go.micro.srv.auth.Update", err.Error()) } pp := base64.StdEncoding.EncodeToString(h) // to lower req.Account.ClientId = strings.ToLower(req.Account.ClientId) req.Account.Type = strings.ToLower(req.Account.Type) // update if err := db.Update(req.Account, salt, pp); err != nil { return errors.InternalServerError("go.micro.srv.auth.Update", err.Error()) } return nil }
func (s *Account) Read(ctx context.Context, req *account.ReadRequest, rsp *account.ReadResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.auth.Read", "id cannot be blank") } acc, err := db.Read(req.Id) if err != nil { return errors.InternalServerError("go.micro.srv.auth.Read", err.Error()) } rsp.Account = acc return nil }
func (r *Label) Delete(ctx context.Context, req *proto.DeleteRequest, rsp *proto.DeleteResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.router.Label.Delete", "invalid id") } if err := label.Delete(req.Id); err != nil { if err == db.ErrNotFound { return nil } return errors.InternalServerError("go.micro.srv.router.Label.Delete", err.Error()) } return nil }
func Process(ctx context.Context, rec *event.Record) error { if rec == nil { return errors.BadRequest("go.micro.srv.event.Process", "invalid record") } if len(rec.Id) == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid id") } if len(rec.Type) == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid type") } if rec.Timestamp == 0 { return errors.BadRequest("go.micro.srv.event.Process", "invalid timestamp") } if err := db.Create(rec); err != nil { return errors.InternalServerError("go.micro.srv.event.Process", err.Error()) } return nil }
func validateAccount(acc *account.Record, method string) error { if acc == nil { return errors.BadRequest("go.micro.srv.auth."+method, "invalid account") } if len(acc.Id) > 0 && uuid.Parse(acc.Id) == nil { return errors.BadRequest("go.micro.srv.auth."+method, "invalid id") } if len(acc.Type) == 0 { return errors.BadRequest("go.micro.srv.auth."+method, "type cannot be blank") } if len(acc.ClientId) == 0 { return errors.BadRequest("go.micro.srv.auth."+method, "client id cannot be blank") } if len(acc.ClientSecret) == 0 { return errors.BadRequest("go.micro.srv.auth."+method, "client secret cannot be blank") } return nil }
func (r *Router) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.StatsResponse) error { if len(req.Service) == 0 { return errors.BadRequest("go.micro.srv.router.Router.Stats", "invalid service name") } stats, err := router.Stats(req.Service, req.NodeId) if err != nil { return errors.InternalServerError("go.micro.srv.router.Router.Stats", err.Error()) } rsp.Stats = stats return nil }
func (e *Event) Read(ctx context.Context, req *event.ReadRequest, rsp *event.ReadResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.event.Read", "invalid id") } rec, err := db.Read(req.Id) if err != nil { return errors.InternalServerError("go.micro.srv.event.Update", err.Error()) } rsp.Record = rec return nil }
func (h *httpBroker) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { err := errors.BadRequest("go.micro.broker", "Method not allowed") http.Error(w, err.Error(), http.StatusMethodNotAllowed) return } defer req.Body.Close() req.ParseForm() b, err := ioutil.ReadAll(req.Body) if err != nil { errr := errors.InternalServerError("go.micro.broker", fmt.Sprintf("Error reading request body: %v", err)) w.WriteHeader(500) w.Write([]byte(errr.Error())) return } var m *Message if err = json.Unmarshal(b, &m); err != nil { errr := errors.InternalServerError("go.micro.broker", fmt.Sprintf("Error parsing request body: %v", err)) w.WriteHeader(500) w.Write([]byte(errr.Error())) return } topic := m.Header[":topic"] delete(m.Header, ":topic") if len(topic) == 0 { errr := errors.InternalServerError("go.micro.broker", "Topic not found") w.WriteHeader(500) w.Write([]byte(errr.Error())) return } p := &httpPublication{m: m, t: topic} id := req.Form.Get("id") h.RLock() for _, subscriber := range h.subscribers[topic] { if id == subscriber.id { // sub is sync; crufty rate limiting // so we don't hose the cpu subscriber.fn(p) } } h.RUnlock() }
func (r *Label) Read(ctx context.Context, req *proto.ReadRequest, rsp *proto.ReadResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.router.Label.Read", "invalid id") } l, err := label.Read(req.Id) if err != nil { if err == db.ErrNotFound { return errors.NotFound("go.micro.srv.router.Label.Read", err.Error()) } return errors.InternalServerError("go.micro.srv.router.Label.Read", err.Error()) } rsp.Label = l return nil }
func (d *DB) Delete(ctx context.Context, req *mdb.DeleteRequest, rsp *mdb.DeleteResponse) error { if err := validateDB("DB.Delete", req.Database); err != nil { return err } if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.db.DB.Delete", "invalid id") } if err := db.Delete(req.Database, req.Id); err != nil && err == db.ErrNotFound { return nil } else if err != nil { return errors.InternalServerError("go.micro.srv.db.DB.Delete", err.Error()) } return nil }
func (r *Router) Select(ctx context.Context, req *proto.SelectRequest, rsp *proto.SelectResponse) error { // TODO: process filters if len(req.Service) == 0 { return errors.BadRequest("go.micro.srv.router.Router.Select", "invalid service name") } services, err := router.Select(req.Service) if err != nil && err == selector.ErrNotFound { return errors.NotFound("go.micro.srv.router.Router.Select", err.Error()) } else if err != nil { return errors.InternalServerError("go.micro.srv.router.Router.Select", err.Error()) } rsp.Services = services rsp.Expires = time.Now().Unix() + int64(router.DefaultExpiry) return nil }
func (d *DB) Read(ctx context.Context, req *mdb.ReadRequest, rsp *mdb.ReadResponse) error { if err := validateDB("DB.Read", req.Database); err != nil { return err } if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.db.DB.Read", "invalid id") } r, err := db.Read(req.Database, req.Id) if err != nil && err == db.ErrNotFound { return errors.NotFound("go.micro.srv.db.DB.Read", "not found") } else if err != nil { return errors.InternalServerError("go.micro.srv.db.DB.Read", err.Error()) } rsp.Record = r return nil }
func (c *Config) Read(ctx context.Context, req *proto.ReadRequest, rsp *proto.ReadResponse) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.config.Read", "invalid id") } ch, err := db.Read(req.Id) if err != nil { return errors.InternalServerError("go.micro.srv.config.Read", err.Error()) } // Set response rsp.Change = ch if len(req.Path) == 0 { rsp.Change.Path = "" rsp.Change.Timestamp = 0 return nil } rsp.Change.Path = req.Path values, err := config.Values(&conf.ChangeSet{ Timestamp: time.Unix(ch.ChangeSet.Timestamp, 0), Data: []byte(ch.ChangeSet.Data), Checksum: ch.ChangeSet.Checksum, Source: ch.ChangeSet.Source, }) if err != nil { return errors.InternalServerError("go.micro.srv.config.Read", err.Error()) } parts := strings.Split(req.Path, config.PathSplitter) // we just want to pass back bytes rsp.Change.ChangeSet.Data = string(values.Get(parts...).Bytes()) return nil }
func (c *Config) Watch(ctx context.Context, req *proto.WatchRequest, stream proto.Config_WatchStream) error { if len(req.Id) == 0 { return errors.BadRequest("go.micro.srv.config.Watch", "invalid id") } watch, err := config.Watch(req.Id) if err != nil { return errors.InternalServerError("go.micro.srv.config.Watch", err.Error()) } defer watch.Stop() for { ch, err := watch.Next() if err != nil { stream.Close() return errors.InternalServerError("go.micro.srv.config.Watch", err.Error()) } if err := stream.Send(ch); err != nil { stream.Close() return errors.InternalServerError("go.micro.srv.config.Watch", err.Error()) } } }