diff --git a/influxql/ast.go b/influxql/ast.go index 259764d746..46905d1aa4 100644 --- a/influxql/ast.go +++ b/influxql/ast.go @@ -92,6 +92,9 @@ func (*DropRetentionPolicyStatement) node() {} func (*DropSeriesStatement) node() {} func (*DropUserStatement) node() {} func (*GrantStatement) node() {} +func (*RevokeStatement) node() {} +func (*SelectStatement) node() {} +func (*SetPasswordUserStatement) node() {} func (*ShowContinuousQueriesStatement) node() {} func (*ShowGrantsForUserStatement) node() {} func (*ShowServersStatement) node() {} @@ -105,9 +108,6 @@ func (*ShowDiagnosticsStatement) node() {} func (*ShowTagKeysStatement) node() {} func (*ShowTagValuesStatement) node() {} func (*ShowUsersStatement) node() {} -func (*RevokeStatement) node() {} -func (*SelectStatement) node() {} -func (*SetPasswordUserStatement) node() {} func (*BinaryExpr) node() {} func (*BooleanLiteral) node() {} diff --git a/influxql/parser.go b/influxql/parser.go index 5210b0e951..e60bcef303 100644 --- a/influxql/parser.go +++ b/influxql/parser.go @@ -94,7 +94,7 @@ func (p *Parser) ParseStatement() (Statement, error) { case ALTER: return p.parseAlterStatement() case SET: - return p.parseSetStatement() + return p.parseSetPasswordUserStatement() default: return nil, newParseError(tokstr(tok, lit), []string{"SELECT", "DELETE", "SHOW", "CREATE", "DROP", "GRANT", "REVOKE", "ALTER", "SET"}, pos) } @@ -207,19 +207,14 @@ func (p *Parser) parseAlterStatement() (Statement, error) { return nil, newParseError(tokstr(tok, lit), []string{"RETENTION"}, pos) } -// parseSetStatement parses a string and returns a set statement. +// parseSetPasswordUserStatement parses a string and returns a set statement. // This function assumes the SET token has already been consumed. -func (p *Parser) parseSetStatement() (*SetPasswordUserStatement, error) { +func (p *Parser) parseSetPasswordUserStatement() (*SetPasswordUserStatement, error) { stmt := &SetPasswordUserStatement{} - // Consume the required PASSWORD token. - if tok, pos, lit := p.scanIgnoreWhitespace(); tok != PASSWORD { - return nil, newParseError(tokstr(tok, lit), []string{"PASSWORD"}, pos) - } - - // Consume the required FOR token. - if tok, pos, lit := p.scanIgnoreWhitespace(); tok != FOR { - return nil, newParseError(tokstr(tok, lit), []string{"FOR"}, pos) + // Consume the required PASSWORD FOR tokens. + if err := p.parseTokens([]Token{PASSWORD, FOR}); err != nil { + return nil, err } // Parse username diff --git a/meta/store.go b/meta/store.go index 31e862b9dd..2d0a7ff066 100644 --- a/meta/store.go +++ b/meta/store.go @@ -96,6 +96,9 @@ type Store struct { // The amount of time without an apply before sending a heartbeat. CommitTimeout time.Duration + // Authentication cache. + authCache map[string]string + Logger *log.Logger } @@ -116,6 +119,7 @@ func NewStore(c Config) *Store { ElectionTimeout: time.Duration(c.ElectionTimeout), LeaderLeaseTimeout: time.Duration(c.LeaderLeaseTimeout), CommitTimeout: time.Duration(c.CommitTimeout), + authCache: make(map[string]string, 0), Logger: log.New(os.Stderr, "", log.LstdFlags), } } @@ -994,11 +998,19 @@ func (s *Store) Authenticate(username, password string) (ui *UserInfo, err error return ErrUserNotFound } + // Check the local auth cache first. + if p, ok := s.authCache[username]; ok && p == password { + ui = u + return nil + } + // Compare password with user hash. if err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(password)); err != nil { return err } + s.authCache[username] = password + ui = u return nil }) @@ -1578,6 +1590,7 @@ func (fsm *storeFSM) applyDropUserCommand(cmd *internal.Command) interface{} { return err } fsm.data = other + delete(fsm.authCache, v.GetName()) return nil } @@ -1591,6 +1604,7 @@ func (fsm *storeFSM) applyUpdateUserCommand(cmd *internal.Command) interface{} { return err } fsm.data = other + delete(fsm.authCache, v.GetName()) return nil }