Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several statements were missing the DefaultDatabase method #8187

Merged
merged 1 commit into from
Apr 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions influxql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,11 @@ func (s *DropRetentionPolicyStatement) RequiredPrivileges() (ExecutionPrivileges
return ExecutionPrivileges{{Admin: false, Name: s.Database, Privilege: WritePrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *DropRetentionPolicyStatement) DefaultDatabase() string {
return s.Database
}

// CreateUserStatement represents a command for creating a new user.
type CreateUserStatement struct {
// Name of the user to be created.
Expand Down Expand Up @@ -704,6 +709,11 @@ func (s *GrantStatement) RequiredPrivileges() (ExecutionPrivileges, error) {
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *GrantStatement) DefaultDatabase() string {
return s.On
}

// GrantAdminStatement represents a command for granting admin privilege.
type GrantAdminStatement struct {
// Who to grant the privilege to.
Expand Down Expand Up @@ -802,6 +812,11 @@ func (s *RevokeStatement) RequiredPrivileges() (ExecutionPrivileges, error) {
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *RevokeStatement) DefaultDatabase() string {
return s.On
}

// RevokeAdminStatement represents a command to revoke admin privilege from a user.
type RevokeAdminStatement struct {
// Who to revoke admin privilege from.
Expand Down Expand Up @@ -868,6 +883,11 @@ func (s *CreateRetentionPolicyStatement) RequiredPrivileges() (ExecutionPrivileg
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *CreateRetentionPolicyStatement) DefaultDatabase() string {
return s.Database
}

// AlterRetentionPolicyStatement represents a command to alter an existing retention policy.
type AlterRetentionPolicyStatement struct {
// Name of policy to alter.
Expand Down Expand Up @@ -924,6 +944,11 @@ func (s *AlterRetentionPolicyStatement) RequiredPrivileges() (ExecutionPrivilege
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *AlterRetentionPolicyStatement) DefaultDatabase() string {
return s.Database
}

// FillOption represents different options for filling aggregate windows.
type FillOption int

Expand Down Expand Up @@ -2558,6 +2583,14 @@ func (s *DeleteStatement) RequiredPrivileges() (ExecutionPrivileges, error) {
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: WritePrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *DeleteStatement) DefaultDatabase() string {
if m, ok := s.Source.(*Measurement); ok {
return m.Database
}
return ""
}

// ShowSeriesStatement represents a command for listing series in the database.
type ShowSeriesStatement struct {
// Database to query. If blank, use the default database.
Expand Down Expand Up @@ -2619,6 +2652,11 @@ func (s *ShowSeriesStatement) RequiredPrivileges() (ExecutionPrivileges, error)
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowSeriesStatement) DefaultDatabase() string {
return s.Database
}

// DropSeriesStatement represents a command for removing a series from the database.
type DropSeriesStatement struct {
// Data source that fields are extracted from (optional)
Expand Down Expand Up @@ -2842,6 +2880,11 @@ func (s *DropContinuousQueryStatement) RequiredPrivileges() (ExecutionPrivileges
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: WritePrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *DropContinuousQueryStatement) DefaultDatabase() string {
return s.Database
}

// ShowMeasurementsStatement represents a command for listing measurements.
type ShowMeasurementsStatement struct {
// Database to query. If blank, use the default database.
Expand Down Expand Up @@ -2906,6 +2949,11 @@ func (s *ShowMeasurementsStatement) RequiredPrivileges() (ExecutionPrivileges, e
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowMeasurementsStatement) DefaultDatabase() string {
return s.Database
}

// DropMeasurementStatement represents a command to drop a measurement.
type DropMeasurementStatement struct {
// Name of the measurement to be dropped.
Expand Down Expand Up @@ -2960,6 +3008,11 @@ func (s *ShowRetentionPoliciesStatement) RequiredPrivileges() (ExecutionPrivileg
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowRetentionPoliciesStatement) DefaultDatabase() string {
return s.Database
}

// ShowStatsStatement displays statistics for a given module.
type ShowStatsStatement struct {
Module string
Expand Down Expand Up @@ -3061,6 +3114,11 @@ func (s *CreateSubscriptionStatement) RequiredPrivileges() (ExecutionPrivileges,
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *CreateSubscriptionStatement) DefaultDatabase() string {
return s.Database
}

// DropSubscriptionStatement represents a command to drop a subscription to the incoming data stream.
type DropSubscriptionStatement struct {
Name string
Expand All @@ -3078,6 +3136,11 @@ func (s *DropSubscriptionStatement) RequiredPrivileges() (ExecutionPrivileges, e
return ExecutionPrivileges{{Admin: true, Name: "", Privilege: AllPrivileges}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *DropSubscriptionStatement) DefaultDatabase() string {
return s.Database
}

// ShowSubscriptionsStatement represents a command to show a list of subscriptions.
type ShowSubscriptionsStatement struct {
}
Expand Down Expand Up @@ -3165,6 +3228,11 @@ func (s *ShowTagKeysStatement) RequiredPrivileges() (ExecutionPrivileges, error)
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowTagKeysStatement) DefaultDatabase() string {
return s.Database
}

// ShowTagValuesStatement represents a command for listing tag values.
type ShowTagValuesStatement struct {
// Database to query. If blank, use the default database.
Expand Down Expand Up @@ -3239,6 +3307,11 @@ func (s *ShowTagValuesStatement) RequiredPrivileges() (ExecutionPrivileges, erro
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowTagValuesStatement) DefaultDatabase() string {
return s.Database
}

// ShowUsersStatement represents a command for listing users.
type ShowUsersStatement struct{}

Expand Down Expand Up @@ -3305,6 +3378,11 @@ func (s *ShowFieldKeysStatement) RequiredPrivileges() (ExecutionPrivileges, erro
return ExecutionPrivileges{{Admin: false, Name: "", Privilege: ReadPrivilege}}, nil
}

// DefaultDatabase returns the default database from the statement.
func (s *ShowFieldKeysStatement) DefaultDatabase() string {
return s.Database
}

// Fields represents a list of fields.
type Fields []*Field

Expand Down
97 changes: 97 additions & 0 deletions influxql/ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package influxql_test

import (
"fmt"
"go/importer"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -1700,6 +1701,102 @@ func TestParse_Errors(t *testing.T) {
}
}

// This test checks to ensure that we have given thought to the database
// context required for security checks. If a new statement is added, this
// test will fail until it is categorized into the correct bucket below.
func Test_EnforceHasDefaultDatabase(t *testing.T) {
pkg, err := importer.Default().Import("github.com/influxdata/influxdb/influxql")
if err != nil {
fmt.Printf("error: %s\n", err.Error())
return
}
statements := []string{}

// this is a list of statements that do not have a database context
exemptStatements := []string{
"CreateDatabaseStatement",
"CreateUserStatement",
"DeleteSeriesStatement",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this one can have a database. There don't appear to be any docs on DeleteSeries so not 100% sure but the type has a source

Sources Sources

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can have multiple sources, so the iterators have to handle security. DefaultDatabase would not be appropriate for this one.

"DropDatabaseStatement",
"DropMeasurementStatement",
"DropSeriesStatement",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Sources Sources

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. If you have multiple sources, DefaultDatabase is the wrong mechanism to use.

"DropShardStatement",
"DropUserStatement",
"GrantAdminStatement",
"KillQueryStatement",
"RevokeAdminStatement",
"SelectStatement",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this one is handled separately but it has a default database for sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it has the potential to have multiple databases, so it doesn't have a DefaultDatabase, which is why it is enforced at the iterator level.

"SetPasswordUserStatement",
"ShowContinuousQueriesStatement",
"ShowDatabasesStatement",
"ShowDiagnosticsStatement",
"ShowGrantsForUserStatement",
"ShowQueriesStatement",
"ShowShardGroupsStatement",
"ShowShardsStatement",
"ShowStatsStatement",
"ShowSubscriptionsStatement",
"ShowUsersStatement",
}

exists := func(stmt string) bool {
switch stmt {
// These are functions with the word statement in them, and can be ignored
case "Statement", "MustParseStatement", "ParseStatement", "RewriteStatement":
return true
default:
// check the exempt statements
for _, s := range exemptStatements {
if s == stmt {
return true
}
}
// check the statements that passed the interface test for HasDefaultDatabase
for _, s := range statements {
if s == stmt {
return true
}
}
return false
}
}

needsHasDefault := []interface{}{
&influxql.AlterRetentionPolicyStatement{},
&influxql.CreateContinuousQueryStatement{},
&influxql.CreateRetentionPolicyStatement{},
&influxql.CreateSubscriptionStatement{},
&influxql.DeleteStatement{},
&influxql.DropContinuousQueryStatement{},
&influxql.DropRetentionPolicyStatement{},
&influxql.DropSubscriptionStatement{},
&influxql.GrantStatement{},
&influxql.RevokeStatement{},
&influxql.ShowFieldKeysStatement{},
&influxql.ShowMeasurementsStatement{},
&influxql.ShowRetentionPoliciesStatement{},
&influxql.ShowSeriesStatement{},
&influxql.ShowTagKeysStatement{},
&influxql.ShowTagValuesStatement{},
}

for _, stmt := range needsHasDefault {
statements = append(statements, strings.TrimPrefix(fmt.Sprintf("%T", stmt), "*influxql."))
if _, ok := stmt.(influxql.HasDefaultDatabase); !ok {
t.Errorf("%T was expected to declare DefaultDatabase method", stmt)
}

}

for _, declName := range pkg.Scope().Names() {
if strings.HasSuffix(declName, "Statement") {
if !exists(declName) {
t.Errorf("unchecked statement %s. please update this test to determine if this statement needs to declare 'DefaultDatabase'", declName)
}
}
}
}

// Valuer represents a simple wrapper around a map to implement the influxql.Valuer interface.
type Valuer map[string]interface{}

Expand Down