mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
This fixes the OriginalIP and RequestUserID in the main featurebase
package, and the Access and Refresh tokens, the UserInfo, and the
[]string of Indexes passed with context.Context(s) in the authn package.
An empty struct was used for all of these keys (and relevant helper
functions we added) to avoid allocations where possible while still
using the context functionality.
Some of the logic in the server.GetIndexes function was fixed.
(cherry picked from commit 0f5a56c958)
136 lines
3.3 KiB
Go
136 lines
3.3 KiB
Go
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package sql
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
pilosa "github.com/featurebasedb/featurebase/v3"
|
|
pproto "github.com/featurebasedb/featurebase/v3/proto"
|
|
"github.com/pkg/errors"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
"vitess.io/vitess/go/vt/sqlparser"
|
|
)
|
|
|
|
// ShowHandler executes SQL show table/field statements
|
|
type ShowHandler struct {
|
|
api *pilosa.API
|
|
}
|
|
|
|
// NewShowHandler constructor
|
|
func NewShowHandler(api *pilosa.API) *ShowHandler {
|
|
return &ShowHandler{
|
|
api: api,
|
|
}
|
|
}
|
|
|
|
// Handle executes mapped SQL
|
|
func (s *ShowHandler) Handle(ctx context.Context, mapped *MappedSQL) (pproto.ToRowser, error) {
|
|
stmt, ok := mapped.Statement.(*sqlparser.Show)
|
|
if !ok {
|
|
return nil, fmt.Errorf("statement is not type show: %T", mapped.Statement)
|
|
}
|
|
|
|
switch stmt.Type {
|
|
case "tables":
|
|
return s.execShowTables(ctx, stmt)
|
|
case "fields":
|
|
return s.execShowFields(ctx, stmt)
|
|
default:
|
|
return nil, fmt.Errorf("cannot show: %s", stmt.Type)
|
|
}
|
|
}
|
|
|
|
func (s *ShowHandler) execShowTables(ctx context.Context, showStmt *sqlparser.Show) (pproto.ToRowser, error) {
|
|
indexInfo, err := s.api.Schema(ctx, false)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "getting schema")
|
|
}
|
|
|
|
allowed, ok := authn.GetIndexes(ctx)
|
|
|
|
result := make(pproto.ConstRowser, 0)
|
|
for _, ii := range indexInfo {
|
|
if ok {
|
|
// if authorization is turned on, allowed will be a list
|
|
// so we have to check if the index is in the allowed list
|
|
found := false
|
|
for _, idx := range allowed {
|
|
if ii.Name == idx {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
continue
|
|
}
|
|
}
|
|
result = append(result, pproto.RowResponse{
|
|
Headers: []*pproto.ColumnInfo{
|
|
{Name: "Table", Datatype: "string"},
|
|
},
|
|
Columns: []*pproto.ColumnResponse{
|
|
{ColumnVal: &pproto.ColumnResponse_StringVal{StringVal: ii.Name}},
|
|
},
|
|
})
|
|
}
|
|
|
|
// Sort the result.
|
|
return OrderBy(result, []string{"Table"}, []string{"asc"}), nil
|
|
}
|
|
|
|
func (s *ShowHandler) execShowFields(ctx context.Context, showStmt *sqlparser.Show) (pproto.ToRowser, error) {
|
|
indexName := showStmt.OnTable.ToViewName().Name.String()
|
|
allowed, ok := authn.GetIndexes(ctx)
|
|
if ok {
|
|
found := false
|
|
for _, idx := range allowed {
|
|
if idx == indexName {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return nil, status.Error(codes.PermissionDenied, "insufficient permissions to access requested tables")
|
|
}
|
|
}
|
|
index, err := s.api.Index(ctx, indexName)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "getting schema")
|
|
}
|
|
if index == nil {
|
|
return nil, errors.WithMessage(pilosa.ErrIndexNotFound, indexName)
|
|
}
|
|
fields := index.Fields()
|
|
|
|
result := make(pproto.ConstRowser, 0, len(fields))
|
|
for _, f := range fields {
|
|
if f.Name() == "_exists" {
|
|
continue
|
|
}
|
|
|
|
typeName := f.Type()
|
|
if f.Keys() {
|
|
typeName = "keyed-" + typeName
|
|
}
|
|
if f.ForeignIndex() != "" {
|
|
typeName = "foreign-" + typeName
|
|
}
|
|
|
|
result = append(result, pproto.RowResponse{
|
|
Headers: []*pproto.ColumnInfo{
|
|
{Name: "Field", Datatype: "string"},
|
|
{Name: "Type", Datatype: "string"},
|
|
},
|
|
Columns: []*pproto.ColumnResponse{
|
|
{ColumnVal: &pproto.ColumnResponse_StringVal{StringVal: f.Name()}},
|
|
{ColumnVal: &pproto.ColumnResponse_StringVal{StringVal: typeName}},
|
|
},
|
|
})
|
|
}
|
|
|
|
// Sort the result.
|
|
return OrderBy(result, []string{"Field"}, []string{"asc"}), nil
|
|
}
|