func (self *Permissions) AuthorizeChangeDbUserPassword(user common.User, db string, targetUsername string) (ok bool, err common.AuthorizationError) { if !user.IsDbAdmin(db) && !(user.GetDb() == db && user.GetName() == targetUsername) { return false, common.NewAuthorizationError("Insufficient permissions to change db user password for %s on %s", targetUsername, db) } return true, "" }
// Distributes the query across the cluster and combines the results. Yields as they come in ensuring proper order. // TODO: make this work even if there is a downed server in the cluster func (self *CoordinatorImpl) DistributeQuery(user common.User, db string, query *parser.SelectQuery, localOnly bool, yield func(*protocol.Series) error) error { if self.clusterConfiguration.IsSingleServer() || localOnly { return self.datastore.ExecuteQuery(user, db, query, yield, nil) } servers, replicationFactor := self.clusterConfiguration.GetServersToMakeQueryTo(&db) id := atomic.AddUint32(&self.requestId, uint32(1)) userName := user.GetName() isDbUser := !user.IsClusterAdmin() responseChannels := make([]chan *protocol.Response, 0, len(servers)+1) queryString := query.GetQueryString() var localServerToQuery *serverToQuery for _, server := range servers { if server.server.Id == self.clusterConfiguration.localServerId { localServerToQuery = server } else { request := &protocol.Request{Type: &queryRequest, Query: &queryString, Id: &id, Database: &db, UserName: &userName, IsDbUser: &isDbUser} if server.ringLocationsToQuery != replicationFactor { r := server.ringLocationsToQuery request.RingLocationsToQuery = &r } responseChan := make(chan *protocol.Response, 3) server.server.MakeRequest(request, responseChan) responseChannels = append(responseChannels, responseChan) } } local := make(chan *protocol.Response) nextPointMap := make(map[string]*NextPoint) // TODO: this style of wrapping the series in response objects with the // last point time is duplicated in the request handler. Refactor... sendFromLocal := func(series *protocol.Series) error { response := createResponse(nextPointMap, series, nil) local <- response return nil } responseChannels = append(responseChannels, local) // TODO: wire up the willreturnsingleseries method and uncomment this line and delete the next one. // isSingleSeriesQuery := query.WillReturnSingleSeries() isSingleSeriesQuery := false go func() { var ringFilter func(database, series *string, time *int64) bool if replicationFactor != localServerToQuery.ringLocationsToQuery { ringFilter = self.clusterConfiguration.GetRingFilterFunction(db, localServerToQuery.ringLocationsToQuery) } self.datastore.ExecuteQuery(user, db, query, sendFromLocal, ringFilter) local <- &protocol.Response{Type: &endStreamResponse} close(local) }() self.streamResultsFromChannels(isSingleSeriesQuery, query.Ascending, responseChannels, yield) return nil }
func (self *CoordinatorImpl) ListSeries(user common.User, database string) ([]*protocol.Series, error) { if self.clusterConfiguration.IsSingleServer() { dbs := []string{} self.datastore.GetSeriesForDatabase(database, func(db string) error { dbs = append(dbs, db) return nil }) return seriesFromListSeries(dbs), nil } servers, replicationFactor := self.clusterConfiguration.GetServersToMakeQueryTo(&database) id := atomic.AddUint32(&self.requestId, uint32(1)) userName := user.GetName() isDbUser := !user.IsClusterAdmin() responseChannels := make([]chan *protocol.Response, 0, len(servers)+1) for _, server := range servers { if server.server.Id == self.clusterConfiguration.localServerId { continue } request := &protocol.Request{Type: &listSeriesRequest, Id: &id, Database: &database, UserName: &userName, IsDbUser: &isDbUser} if server.ringLocationsToQuery != replicationFactor { r := server.ringLocationsToQuery request.RingLocationsToQuery = &r } responseChan := make(chan *protocol.Response, 3) server.server.protobufClient.MakeRequest(request, responseChan) responseChannels = append(responseChannels, responseChan) } local := make(chan *protocol.Response) responseChannels = append(responseChannels, local) go func() { dbs := []string{} self.datastore.GetSeriesForDatabase(database, func(db string) error { dbs = append(dbs, db) return nil }) seriesArray := seriesFromListSeries(dbs) for _, series := range seriesArray { local <- &protocol.Response{Type: &listSeriesResponse, Series: series} } local <- &protocol.Response{Type: &endStreamResponse} close(local) }() seriesArray := []*protocol.Series{} self.streamResultsFromChannels(true, true, responseChannels, func(series *protocol.Series) error { seriesArray = append(seriesArray, series) return nil }) return seriesArray, nil }
func (self *CoordinatorImpl) ChangeDbUserPassword(requester common.User, db, username, password string) error { if !requester.IsClusterAdmin() && !requester.IsDbAdmin(db) && !(requester.GetDb() == db && requester.GetName() == username) { return common.NewAuthorizationError("Insufficient permissions") } hash, err := cluster.HashPassword(password) if err != nil { return err } return self.raftServer.ChangeDbUserPassword(db, username, hash) }
func (self *CoordinatorImpl) RunQuery(user common.User, database string, queryString string, seriesWriter SeriesWriter) (err error) { log.Info("Query: db: %s, u: %s, q: %s", database, user.GetName(), queryString) // don't let a panic pass beyond RunQuery defer common.RecoverFunc(database, queryString, nil) q, err := parser.ParseQuery(queryString) if err != nil { return err } for _, query := range q { querySpec := parser.NewQuerySpec(user, database, query) if query.DeleteQuery != nil { if err := self.clusterConfiguration.CreateCheckpoint(); err != nil { return err } if err := self.runDeleteQuery(querySpec, seriesWriter); err != nil { return err } continue } if query.DropQuery != nil { if err := self.DeleteContinuousQuery(user, database, uint32(query.DropQuery.Id)); err != nil { return err } continue } if query.IsListQuery() { if query.IsListSeriesQuery() { self.runListSeriesQuery(querySpec, seriesWriter) } else if query.IsListContinuousQueriesQuery() { queries, err := self.ListContinuousQueries(user, database) if err != nil { return err } for _, q := range queries { if err := seriesWriter.Write(q); err != nil { return err } } } continue } if query.DropSeriesQuery != nil { err := self.runDropSeriesQuery(querySpec, seriesWriter) if err != nil { return err } continue } selectQuery := query.SelectQuery if selectQuery.IsContinuousQuery() { return self.CreateContinuousQuery(user, database, queryString) } if err := self.checkPermission(user, querySpec); err != nil { return err } return self.runQuery(querySpec, seriesWriter) } seriesWriter.Close() return nil }
func (self *CoordinatorImpl) WriteSeriesData(user common.User, db string, series []*protocol.Series) error { // make sure that the db exist if !self.clusterConfiguration.DatabasesExists(db) { return fmt.Errorf("Database %s doesn't exist", db) } for _, s := range series { seriesName := s.GetName() if user.HasWriteAccess(seriesName) { continue } return common.NewAuthorizationError("User %s doesn't have write permissions for %s", user.GetName(), seriesName) } err := self.CommitSeriesData(db, series, false) if err != nil { return err } for _, s := range series { self.ProcessContinuousQueries(db, s) } return err }
func (self *CoordinatorImpl) WriteSeriesData(user common.User, db string, series []*protocol.Series) error { for _, s := range series { seriesName := s.GetName() if user.HasWriteAccess(seriesName) { continue } return common.NewAuthorizationError("User %s doesn't have write permissions for %s", user.GetName(), seriesName) } err := self.CommitSeriesData(db, series, false) if err != nil { return err } for _, s := range series { self.ProcessContinuousQueries(db, s) } return err }
func (self *CoordinatorImpl) ChangeDbUserPassword(requester common.User, db, username, password string) error { if !requester.IsClusterAdmin() && !requester.IsDbAdmin(db) && !(requester.GetDb() == db && requester.GetName() == username) { return fmt.Errorf("Insufficient permissions") } dbUsers := self.clusterConfiguration.dbUsers[db] if dbUsers == nil || dbUsers[username] == nil { return fmt.Errorf("Invalid username %s", username) } dbUsers[username].changePassword(password) return self.raftServer.SaveDbUser(dbUsers[username]) }
// Distributes the query across the cluster and combines the results. Yields as they come in ensuring proper order. // TODO: make this work even if there is a downed server in the cluster func (self *CoordinatorImpl) DistributeQuery(user common.User, db string, query *parser.SelectQuery, yield func(*protocol.Series) error) error { if self.clusterConfiguration.IsSingleServer() { return self.datastore.ExecuteQuery(user, db, query, yield, nil) } servers, replicationFactor := self.clusterConfiguration.GetServersToMakeQueryTo(self.localHostId, &db) queryString := query.GetQueryString() id := atomic.AddUint32(&self.requestId, uint32(1)) userName := user.GetName() responseChannels := make([]chan *protocol.Response, 0, len(servers)+1) var localServerToQuery *serverToQuery for _, server := range servers { if server.server.Id == self.localHostId { localServerToQuery = server } else { request := &protocol.Request{Type: &queryRequest, Query: &queryString, Id: &id, Database: &db, UserName: &userName} if server.ringLocationsToQuery != replicationFactor { r := server.ringLocationsToQuery request.RingLocationsToQuery = &r } responseChan := make(chan *protocol.Response, 3) server.server.protobufClient.MakeRequest(request, responseChan) responseChannels = append(responseChannels, responseChan) } } local := make(chan *protocol.Response) nextPointMap := make(map[string]*protocol.Point) // TODO: this style of wrapping the series in response objects with the // last point time is duplicated in the request handler. Refactor... sendFromLocal := func(series *protocol.Series) error { pointCount := len(series.Points) if pointCount == 0 { if nextPoint := nextPointMap[*series.Name]; nextPoint != nil { series.Points = append(series.Points, nextPoint) } local <- &protocol.Response{Type: &queryResponse, Series: series} return nil } oldNextPoint := nextPointMap[*series.Name] nextPoint := series.Points[pointCount-1] series.Points[pointCount-1] = nil if oldNextPoint != nil { copy(series.Points[1:], series.Points[0:]) series.Points[0] = oldNextPoint } else { series.Points = series.Points[:len(series.Points)-1] } response := &protocol.Response{Series: series, Type: &queryResponse} if nextPoint != nil { nextPointMap[*series.Name] = nextPoint response.NextPointTime = nextPoint.Timestamp } local <- response return nil } responseChannels = append(responseChannels, local) // TODO: wire up the willreturnsingleseries method and uncomment this line and delete the next one. // isSingleSeriesQuery := query.WillReturnSingleSeries() isSingleSeriesQuery := false go func() { var ringFilter func(database, series *string, time *int64) bool if replicationFactor != localServerToQuery.ringLocationsToQuery { ringFilter = self.clusterConfiguration.GetRingFilterFunction(db, localServerToQuery.ringLocationsToQuery) } self.datastore.ExecuteQuery(user, db, query, sendFromLocal, ringFilter) local <- &protocol.Response{Type: &endStreamResponse} close(local) }() self.streamResultsFromChannels(isSingleSeriesQuery, query.Ascending, responseChannels, yield) return nil }