Add correct implementation of mappings

pull/10616/head
Michael Desa 2018-02-05 14:54:39 -05:00
parent 343f417474
commit 64f670e819
22 changed files with 1635 additions and 1455 deletions

View File

@ -41,6 +41,7 @@ type Client struct {
UsersStore *UsersStore
OrganizationsStore *OrganizationsStore
ConfigStore *ConfigStore
MappingsStore *MappingsStore
}
// NewClient initializes all stores
@ -60,6 +61,7 @@ func NewClient() *Client {
c.UsersStore = &UsersStore{client: c}
c.OrganizationsStore = &OrganizationsStore{client: c}
c.ConfigStore = &ConfigStore{client: c}
c.MappingsStore = &MappingsStore{client: c}
return c
}
@ -151,6 +153,10 @@ func (c *Client) initialize(ctx context.Context) error {
if _, err := tx.CreateBucketIfNotExists(BuildBucket); err != nil {
return err
}
// Always create Mapping bucket.
if _, err := tx.CreateBucketIfNotExists(MappingsBucket); err != nil {
return err
}
return nil
}); err != nil {
return err
@ -184,6 +190,9 @@ func (c *Client) migrate(ctx context.Context, build chronograf.BuildInfo) error
if err := c.BuildStore.Migrate(ctx, build); err != nil {
return err
}
if err := c.MappingsStore.Migrate(ctx); err != nil {
return err
}
}
return nil
}

View File

@ -578,23 +578,12 @@ func UnmarshalRolePB(data []byte, r *Role) error {
// MarshalOrganization encodes a organization to binary protobuf format.
func MarshalOrganization(o *chronograf.Organization) ([]byte, error) {
mappings := make([]*Mapping, len(o.Mappings))
for i, m := range o.Mappings {
mappings[i] = &Mapping{
Provider: m.Provider,
Scheme: m.Scheme,
Group: m.Group,
GrantedRole: m.GrantedRole,
}
}
return MarshalOrganizationPB(&Organization{
ID: o.ID,
Name: o.Name,
DefaultRole: o.DefaultRole,
Public: o.Public,
Mappings: mappings,
})
}
@ -614,19 +603,6 @@ func UnmarshalOrganization(data []byte, o *chronograf.Organization) error {
o.DefaultRole = pb.DefaultRole
o.Public = pb.Public
mappings := make([]chronograf.Mapping, len(pb.Mappings))
for i, m := range pb.Mappings {
mappings[i] = chronograf.Mapping{
Provider: m.Provider,
Scheme: m.Scheme,
Group: m.Group,
GrantedRole: m.GrantedRole,
}
}
o.Mappings = mappings
return nil
}
@ -673,3 +649,44 @@ func UnmarshalConfigPB(data []byte, c *Config) error {
}
return nil
}
// MarshalMapping encodes a mapping to binary protobuf format.
func MarshalMapping(m *chronograf.Mapping) ([]byte, error) {
return MarshalMappingPB(&Mapping{
Provider: m.Provider,
Scheme: m.Scheme,
Group: m.Group,
ID: m.ID,
Organization: m.Organization,
})
}
// MarshalMappingPB encodes a mapping to binary protobuf format.
func MarshalMappingPB(m *Mapping) ([]byte, error) {
return proto.Marshal(m)
}
// UnmarshalMapping decodes a mapping from binary protobuf data.
func UnmarshalMapping(data []byte, m *chronograf.Mapping) error {
var pb Mapping
if err := UnmarshalMappingPB(data, &pb); err != nil {
return err
}
m.Provider = pb.Provider
m.Scheme = pb.Scheme
m.Group = pb.Group
m.Organization = pb.Organization
m.ID = pb.ID
return nil
}
// UnmarshalMappingPB decodes a mapping from binary protobuf data.
func UnmarshalMappingPB(data []byte, m *Mapping) error {
if err := proto.Unmarshal(data, m); err != nil {
return err
}
return nil
}

View File

@ -1026,10 +1026,12 @@ func (m *Role) GetName() string {
}
type Mapping struct {
Provider string `protobuf:"bytes,1,opt,name=Provider,proto3" json:"Provider,omitempty"`
Scheme string `protobuf:"bytes,2,opt,name=Scheme,proto3" json:"Scheme,omitempty"`
Group string `protobuf:"bytes,3,opt,name=Group,proto3" json:"Group,omitempty"`
GrantedRole string `protobuf:"bytes,4,opt,name=GrantedRole,proto3" json:"GrantedRole,omitempty"`
Provider string `protobuf:"bytes,1,opt,name=Provider,proto3" json:"Provider,omitempty"`
Scheme string `protobuf:"bytes,2,opt,name=Scheme,proto3" json:"Scheme,omitempty"`
Group string `protobuf:"bytes,3,opt,name=Group,proto3" json:"Group,omitempty"`
// string GrantedRole = 4; // GrantedRole is the name of the role that you will be granted if you match the mapping
ID string `protobuf:"bytes,4,opt,name=ID,proto3" json:"ID,omitempty"`
Organization string `protobuf:"bytes,5,opt,name=Organization,proto3" json:"Organization,omitempty"`
}
func (m *Mapping) Reset() { *m = Mapping{} }
@ -1058,19 +1060,25 @@ func (m *Mapping) GetGroup() string {
return ""
}
func (m *Mapping) GetGrantedRole() string {
func (m *Mapping) GetID() string {
if m != nil {
return m.GrantedRole
return m.ID
}
return ""
}
func (m *Mapping) GetOrganization() string {
if m != nil {
return m.Organization
}
return ""
}
type Organization struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
DefaultRole string `protobuf:"bytes,3,opt,name=DefaultRole,proto3" json:"DefaultRole,omitempty"`
Public bool `protobuf:"varint,4,opt,name=Public,proto3" json:"Public,omitempty"`
Mappings []*Mapping `protobuf:"bytes,5,rep,name=Mappings" json:"Mappings,omitempty"`
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
DefaultRole string `protobuf:"bytes,3,opt,name=DefaultRole,proto3" json:"DefaultRole,omitempty"`
Public bool `protobuf:"varint,4,opt,name=Public,proto3" json:"Public,omitempty"`
}
func (m *Organization) Reset() { *m = Organization{} }
@ -1106,13 +1114,6 @@ func (m *Organization) GetPublic() bool {
return false
}
func (m *Organization) GetMappings() []*Mapping {
if m != nil {
return m.Mappings
}
return nil
}
type Config struct {
Auth *AuthConfig `protobuf:"bytes,1,opt,name=Auth" json:"Auth,omitempty"`
}
@ -1197,93 +1198,92 @@ func init() {
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
var fileDescriptorInternal = []byte{
// 1396 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x5f, 0x8f, 0xdb, 0x44,
0x10, 0x97, 0xe3, 0x38, 0xb1, 0x27, 0xd7, 0x52, 0xcc, 0x89, 0x9a, 0x22, 0xa1, 0x60, 0x81, 0x38,
0x04, 0x3d, 0xd0, 0x55, 0x48, 0x08, 0x01, 0x52, 0xee, 0x82, 0xca, 0xd1, 0x7f, 0xd7, 0x4d, 0xef,
0x78, 0x42, 0xd5, 0xc6, 0x99, 0x24, 0x56, 0x1d, 0xdb, 0xac, 0xed, 0xbb, 0x33, 0x5f, 0x05, 0x09,
0x09, 0x89, 0x4f, 0x80, 0x78, 0xe7, 0x15, 0xf1, 0xca, 0x77, 0xe0, 0x2b, 0xf0, 0x8a, 0x66, 0x77,
0xfd, 0x27, 0x97, 0xb4, 0xea, 0x03, 0xe2, 0x6d, 0x7f, 0x33, 0x9b, 0xd9, 0xd9, 0x99, 0xdf, 0xfc,
0xd6, 0x81, 0xeb, 0x61, 0x9c, 0xa3, 0x88, 0x79, 0xb4, 0x9f, 0x8a, 0x24, 0x4f, 0x5c, 0xbb, 0xc2,
0xfe, 0xdf, 0x1d, 0xe8, 0x4d, 0x92, 0x42, 0x04, 0xe8, 0x5e, 0x87, 0xce, 0xf1, 0xd8, 0x33, 0x86,
0xc6, 0x9e, 0xc9, 0x3a, 0xc7, 0x63, 0xd7, 0x85, 0xee, 0x43, 0xbe, 0x42, 0xaf, 0x33, 0x34, 0xf6,
0x1c, 0x26, 0xd7, 0x64, 0x7b, 0x52, 0xa6, 0xe8, 0x99, 0xca, 0x46, 0x6b, 0xf7, 0x16, 0xd8, 0xa7,
0x19, 0x45, 0x5b, 0xa1, 0xd7, 0x95, 0xf6, 0x1a, 0x93, 0xef, 0x84, 0x67, 0xd9, 0x45, 0x22, 0x66,
0x9e, 0xa5, 0x7c, 0x15, 0x76, 0x6f, 0x80, 0x79, 0xca, 0xee, 0x7b, 0x3d, 0x69, 0xa6, 0xa5, 0xeb,
0x41, 0x7f, 0x8c, 0x73, 0x5e, 0x44, 0xb9, 0xd7, 0x1f, 0x1a, 0x7b, 0x36, 0xab, 0x20, 0xc5, 0x79,
0x82, 0x11, 0x2e, 0x04, 0x9f, 0x7b, 0xb6, 0x8a, 0x53, 0x61, 0x77, 0x1f, 0xdc, 0xe3, 0x38, 0xc3,
0xa0, 0x10, 0x38, 0x79, 0x16, 0xa6, 0x67, 0x28, 0xc2, 0x79, 0xe9, 0x39, 0x32, 0xc0, 0x16, 0x0f,
0x9d, 0xf2, 0x00, 0x73, 0x4e, 0x67, 0x83, 0x0c, 0x55, 0x41, 0xd7, 0x87, 0x9d, 0xc9, 0x92, 0x0b,
0x9c, 0x4d, 0x30, 0x10, 0x98, 0x7b, 0x03, 0xe9, 0x5e, 0xb3, 0xd1, 0x9e, 0x47, 0x62, 0xc1, 0xe3,
0xf0, 0x07, 0x9e, 0x87, 0x49, 0xec, 0xed, 0xa8, 0x3d, 0x6d, 0x1b, 0x55, 0x89, 0x25, 0x11, 0x7a,
0xd7, 0x54, 0x95, 0x68, 0xed, 0xff, 0x66, 0x80, 0x33, 0xe6, 0xd9, 0x72, 0x9a, 0x70, 0x31, 0x7b,
0xa9, 0x5a, 0xdf, 0x06, 0x2b, 0xc0, 0x28, 0xca, 0x3c, 0x73, 0x68, 0xee, 0x0d, 0x0e, 0x6e, 0xee,
0xd7, 0x4d, 0xac, 0xe3, 0x1c, 0x61, 0x14, 0x31, 0xb5, 0xcb, 0xfd, 0x18, 0x9c, 0x1c, 0x57, 0x69,
0xc4, 0x73, 0xcc, 0xbc, 0xae, 0xfc, 0x89, 0xdb, 0xfc, 0xe4, 0x89, 0x76, 0xb1, 0x66, 0xd3, 0xc6,
0x55, 0xac, 0xcd, 0xab, 0xf8, 0x7f, 0x75, 0xe0, 0xda, 0xda, 0x71, 0xee, 0x0e, 0x18, 0x97, 0x32,
0x73, 0x8b, 0x19, 0x97, 0x84, 0x4a, 0x99, 0xb5, 0xc5, 0x8c, 0x92, 0xd0, 0x85, 0xe4, 0x86, 0xc5,
0x8c, 0x0b, 0x42, 0x4b, 0xc9, 0x08, 0x8b, 0x19, 0x4b, 0xf7, 0x7d, 0xe8, 0x7f, 0x5f, 0xa0, 0x08,
0x31, 0xf3, 0x2c, 0x99, 0xdd, 0x2b, 0x4d, 0x76, 0x8f, 0x0b, 0x14, 0x25, 0xab, 0xfc, 0x54, 0x0d,
0xc9, 0x26, 0x45, 0x0d, 0xb9, 0x26, 0x5b, 0x4e, 0xcc, 0xeb, 0x2b, 0x1b, 0xad, 0x75, 0x15, 0x15,
0x1f, 0xa8, 0x8a, 0x9f, 0x40, 0x97, 0x5f, 0x62, 0xe6, 0x39, 0x32, 0xfe, 0xdb, 0xcf, 0x29, 0xd8,
0xfe, 0xe8, 0x12, 0xb3, 0xaf, 0xe2, 0x5c, 0x94, 0x4c, 0x6e, 0x77, 0xdf, 0x83, 0x5e, 0x90, 0x44,
0x89, 0xc8, 0x3c, 0xb8, 0x9a, 0xd8, 0x11, 0xd9, 0x99, 0x76, 0xdf, 0xba, 0x0b, 0x4e, 0xfd, 0x5b,
0xa2, 0xef, 0x33, 0x2c, 0x65, 0x25, 0x1c, 0x46, 0x4b, 0xf7, 0x1d, 0xb0, 0xce, 0x79, 0x54, 0xa8,
0x2e, 0x0e, 0x0e, 0xae, 0x37, 0x61, 0x46, 0x97, 0x61, 0xc6, 0x94, 0xf3, 0xb3, 0xce, 0xa7, 0x86,
0xbf, 0x00, 0x4b, 0x46, 0x6e, 0xf1, 0xc0, 0xa9, 0x78, 0x20, 0xe7, 0xab, 0xd3, 0x9a, 0xaf, 0x1b,
0x60, 0x7e, 0x8d, 0x97, 0x7a, 0xe4, 0x68, 0x59, 0xb3, 0xa5, 0xdb, 0x62, 0xcb, 0x2e, 0x58, 0x67,
0xf2, 0x70, 0xd5, 0x45, 0x05, 0xfc, 0x5f, 0x0d, 0xe8, 0xd2, 0xe1, 0xd4, 0xeb, 0x08, 0x17, 0x3c,
0x28, 0x0f, 0x93, 0x22, 0x9e, 0x65, 0x9e, 0x31, 0x34, 0xf7, 0x4c, 0xb6, 0x66, 0x73, 0x5f, 0x87,
0xde, 0x54, 0x79, 0x3b, 0x43, 0x73, 0xcf, 0x61, 0x1a, 0x51, 0xe8, 0x88, 0x4f, 0x31, 0xd2, 0x29,
0x28, 0x40, 0xbb, 0x53, 0x81, 0xf3, 0xf0, 0x52, 0xa7, 0xa1, 0x11, 0xd9, 0xb3, 0x62, 0x4e, 0x76,
0x95, 0x89, 0x46, 0x94, 0xf4, 0x94, 0x67, 0x75, 0x53, 0x69, 0x4d, 0x91, 0xb3, 0x80, 0x47, 0x55,
0x57, 0x15, 0xf0, 0x7f, 0x37, 0x68, 0xda, 0x15, 0x4b, 0x37, 0x2a, 0xf4, 0x06, 0xd8, 0xc4, 0xe0,
0xa7, 0xe7, 0x5c, 0xe8, 0x2a, 0xf5, 0x09, 0x9f, 0x71, 0xe1, 0x7e, 0x04, 0x3d, 0x59, 0xe2, 0x2d,
0x13, 0x53, 0x85, 0x93, 0x55, 0x61, 0x7a, 0x5b, 0xcd, 0xa9, 0x6e, 0x8b, 0x53, 0xf5, 0x65, 0xad,
0xf6, 0x65, 0x6f, 0x83, 0x45, 0xe4, 0x2c, 0x65, 0xf6, 0x5b, 0x23, 0x2b, 0x0a, 0xab, 0x5d, 0xfe,
0x29, 0x5c, 0x5b, 0x3b, 0xb1, 0x3e, 0xc9, 0x58, 0x3f, 0xa9, 0xa1, 0x8b, 0xa3, 0xe9, 0x41, 0x4a,
0x97, 0x61, 0x84, 0x41, 0x8e, 0x33, 0x59, 0x6f, 0x9b, 0xd5, 0xd8, 0xff, 0xd9, 0x68, 0xe2, 0xca,
0xf3, 0x48, 0xcb, 0x82, 0x64, 0xb5, 0xe2, 0xf1, 0x4c, 0x87, 0xae, 0x20, 0xd5, 0x6d, 0x36, 0xd5,
0xa1, 0x3b, 0xb3, 0x29, 0x61, 0x91, 0xea, 0x0e, 0x76, 0x44, 0xea, 0x0e, 0x61, 0xb0, 0x42, 0x9e,
0x15, 0x02, 0x57, 0x18, 0xe7, 0xba, 0x04, 0x6d, 0x93, 0x7b, 0x13, 0xfa, 0x39, 0x5f, 0x3c, 0x25,
0x92, 0xeb, 0x4e, 0xe6, 0x7c, 0x71, 0x0f, 0x4b, 0xf7, 0x4d, 0x70, 0xe6, 0x21, 0x46, 0x33, 0xe9,
0x52, 0xed, 0xb4, 0xa5, 0xe1, 0x1e, 0x96, 0xfe, 0x1f, 0x06, 0xf4, 0x26, 0x28, 0xce, 0x51, 0xbc,
0x94, 0xc8, 0xb5, 0x1f, 0x0f, 0xf3, 0x05, 0x8f, 0x47, 0x77, 0xfb, 0xe3, 0x61, 0x35, 0x8f, 0xc7,
0x2e, 0x58, 0x13, 0x11, 0x1c, 0x8f, 0x65, 0x46, 0x26, 0x53, 0x80, 0xd8, 0x38, 0x0a, 0xf2, 0xf0,
0x1c, 0xf5, 0x8b, 0xa2, 0xd1, 0x86, 0xf6, 0xd9, 0x5b, 0xb4, 0xef, 0x27, 0x03, 0x7a, 0xf7, 0x79,
0x99, 0x14, 0xf9, 0x06, 0x0b, 0x87, 0x30, 0x18, 0xa5, 0x69, 0x14, 0x06, 0xea, 0xd7, 0xea, 0x46,
0x6d, 0x13, 0xed, 0x78, 0xd0, 0xaa, 0xaf, 0xba, 0x5b, 0xdb, 0x44, 0x72, 0x71, 0x24, 0xf5, 0x5d,
0x89, 0x75, 0x4b, 0x2e, 0x94, 0xac, 0x4b, 0x27, 0x15, 0x61, 0x54, 0xe4, 0xc9, 0x3c, 0x4a, 0x2e,
0xe4, 0x6d, 0x6d, 0x56, 0x63, 0xff, 0xcf, 0x0e, 0x74, 0xff, 0x2f, 0x4d, 0xde, 0x01, 0x23, 0xd4,
0xcd, 0x36, 0xc2, 0x5a, 0xa1, 0xfb, 0x2d, 0x85, 0xf6, 0xa0, 0x5f, 0x0a, 0x1e, 0x2f, 0x30, 0xf3,
0x6c, 0xa9, 0x2e, 0x15, 0x94, 0x1e, 0x39, 0x47, 0x4a, 0x9a, 0x1d, 0x56, 0xc1, 0x7a, 0x2e, 0xa0,
0x35, 0x17, 0x1f, 0x6a, 0x15, 0x1f, 0xc8, 0x8c, 0xbc, 0xf5, 0xb2, 0x5c, 0x15, 0xef, 0xff, 0x4e,
0x93, 0xff, 0x31, 0xc0, 0xaa, 0x87, 0xea, 0x68, 0x7d, 0xa8, 0x8e, 0x9a, 0xa1, 0x1a, 0x1f, 0x56,
0x43, 0x35, 0x3e, 0x24, 0xcc, 0x4e, 0xaa, 0xa1, 0x62, 0x27, 0xd4, 0xac, 0xbb, 0x22, 0x29, 0xd2,
0xc3, 0x52, 0x75, 0xd5, 0x61, 0x35, 0x26, 0x26, 0x7e, 0xbb, 0x44, 0xa1, 0x4b, 0xed, 0x30, 0x8d,
0x88, 0xb7, 0xf7, 0xa5, 0xe0, 0xa8, 0xe2, 0x2a, 0xe0, 0xbe, 0x0b, 0x16, 0xa3, 0xe2, 0xc9, 0x0a,
0xaf, 0xf5, 0x45, 0x9a, 0x99, 0xf2, 0x52, 0x50, 0xf5, 0xf5, 0xa6, 0x09, 0x5c, 0x7d, 0xcb, 0x7d,
0x00, 0xbd, 0xc9, 0x32, 0x9c, 0xe7, 0xd5, 0x5b, 0xf8, 0x5a, 0x4b, 0xb0, 0xc2, 0x15, 0x4a, 0x1f,
0xd3, 0x5b, 0xfc, 0xc7, 0xe0, 0xd4, 0xc6, 0x26, 0x1d, 0xa3, 0x9d, 0x8e, 0x0b, 0xdd, 0xd3, 0x38,
0xcc, 0xab, 0xd1, 0xa5, 0x35, 0x5d, 0xf6, 0x71, 0xc1, 0xe3, 0x3c, 0xcc, 0xcb, 0x6a, 0x74, 0x2b,
0xec, 0xdf, 0xd1, 0xe9, 0x53, 0xb8, 0xd3, 0x34, 0x45, 0xa1, 0x65, 0x40, 0x01, 0x79, 0x48, 0x72,
0x81, 0x4a, 0xc1, 0x4d, 0xa6, 0x80, 0xff, 0x1d, 0x38, 0xa3, 0x08, 0x45, 0xce, 0x8a, 0x08, 0xb7,
0xbd, 0x8c, 0xdf, 0x4c, 0x1e, 0x3d, 0xac, 0x32, 0xa0, 0x75, 0x33, 0xf2, 0xe6, 0x95, 0x91, 0xbf,
0xc7, 0x53, 0x7e, 0x3c, 0x96, 0x3c, 0x37, 0x99, 0x46, 0xfe, 0x2f, 0x06, 0x74, 0x49, 0x5b, 0x5a,
0xa1, 0xbb, 0x2f, 0xd2, 0xa5, 0x13, 0x91, 0x9c, 0x87, 0x33, 0x14, 0xd5, 0xe5, 0x2a, 0x2c, 0x8b,
0x1e, 0x2c, 0xb1, 0x7e, 0x80, 0x35, 0x22, 0xae, 0xd1, 0xa7, 0x5e, 0x35, 0x4b, 0x2d, 0xae, 0x91,
0x99, 0x29, 0xa7, 0xfb, 0x16, 0xc0, 0xa4, 0x48, 0x51, 0x8c, 0x66, 0xab, 0x30, 0x96, 0x4d, 0xb7,
0x59, 0xcb, 0xe2, 0x7f, 0xa9, 0x3e, 0x1e, 0x37, 0x14, 0xca, 0xd8, 0xfe, 0xa1, 0x79, 0x35, 0x73,
0xbf, 0x80, 0xfe, 0x03, 0x9e, 0xa6, 0x61, 0xbc, 0x58, 0xbb, 0x84, 0xf1, 0xdc, 0x4b, 0x74, 0xd6,
0x2e, 0xb1, 0x0b, 0x96, 0xa4, 0x6c, 0xf5, 0xd8, 0x4b, 0x40, 0x6a, 0x76, 0x57, 0xf0, 0x38, 0xc7,
0x99, 0xfc, 0xb0, 0xd5, 0xaf, 0x45, 0xcb, 0xe4, 0xff, 0x68, 0xac, 0xe7, 0xbb, 0xad, 0x81, 0x1b,
0x55, 0x1e, 0xc2, 0x40, 0x7f, 0xe1, 0xcb, 0xb0, 0x5a, 0x24, 0x5b, 0x26, 0x4a, 0xf3, 0xa4, 0x98,
0x46, 0x61, 0x20, 0xcf, 0xb4, 0x99, 0x46, 0xee, 0x6d, 0xb0, 0xf5, 0x2d, 0xab, 0x72, 0xbf, 0xda,
0x94, 0x5b, 0x7b, 0x58, 0xbd, 0xc5, 0x3f, 0x80, 0xde, 0x51, 0x12, 0xcf, 0xc3, 0x85, 0xbb, 0x07,
0xdd, 0x51, 0x91, 0x2f, 0x65, 0x62, 0x83, 0x83, 0xdd, 0x96, 0x1e, 0x14, 0xf9, 0x52, 0xed, 0x61,
0x72, 0x87, 0xff, 0x39, 0x40, 0x63, 0xa3, 0x7f, 0x19, 0x4d, 0x93, 0x1e, 0xe2, 0x05, 0x31, 0x29,
0x93, 0x51, 0x6c, 0xb6, 0xc5, 0xe3, 0x7f, 0x01, 0xce, 0x61, 0x11, 0x46, 0xb3, 0xe3, 0x78, 0x9e,
0x90, 0xa2, 0x9c, 0xa1, 0xc8, 0x9a, 0x36, 0x56, 0x90, 0xee, 0x47, 0xe2, 0x52, 0x8f, 0x96, 0x46,
0xd3, 0x9e, 0xfc, 0xa3, 0x76, 0xe7, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x6a, 0xf4, 0x02,
0xba, 0x0d, 0x00, 0x00,
// 1377 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xcf, 0x8e, 0xe3, 0xc4,
0x13, 0x96, 0x63, 0x3b, 0x89, 0x2b, 0xb3, 0xfb, 0x5b, 0xf9, 0x37, 0x62, 0xcd, 0x22, 0xa1, 0x60,
0x81, 0x08, 0x82, 0x1d, 0xd0, 0xac, 0x90, 0x10, 0x02, 0xa4, 0xcc, 0x04, 0x2d, 0xc3, 0xfe, 0x9b,
0xed, 0xec, 0x0c, 0x27, 0xb4, 0xea, 0x38, 0x95, 0xc4, 0x5a, 0xc7, 0x36, 0x6d, 0x7b, 0x26, 0xe6,
0x05, 0x78, 0x0b, 0x24, 0x24, 0x9e, 0x00, 0x71, 0xe7, 0x8a, 0xb8, 0xf2, 0x0e, 0xbc, 0x02, 0x57,
0x54, 0xdd, 0x6d, 0xc7, 0x99, 0x64, 0x57, 0x73, 0x40, 0xdc, 0xfa, 0xab, 0xea, 0x54, 0x57, 0x57,
0x7d, 0xf5, 0xb5, 0x03, 0x37, 0xc3, 0x38, 0x47, 0x11, 0xf3, 0xe8, 0x20, 0x15, 0x49, 0x9e, 0xb8,
0xdd, 0x0a, 0xfb, 0x7f, 0xb5, 0xa0, 0x3d, 0x4e, 0x0a, 0x11, 0xa0, 0x7b, 0x13, 0x5a, 0x27, 0x23,
0xcf, 0xe8, 0x1b, 0x03, 0x93, 0xb5, 0x4e, 0x46, 0xae, 0x0b, 0xd6, 0x63, 0xbe, 0x44, 0xaf, 0xd5,
0x37, 0x06, 0x0e, 0x93, 0x6b, 0xb2, 0x3d, 0x2b, 0x53, 0xf4, 0x4c, 0x65, 0xa3, 0xb5, 0x7b, 0x07,
0xba, 0x67, 0x19, 0x45, 0x5b, 0xa2, 0x67, 0x49, 0x7b, 0x8d, 0xc9, 0x77, 0xca, 0xb3, 0xec, 0x32,
0x11, 0x53, 0xcf, 0x56, 0xbe, 0x0a, 0xbb, 0xb7, 0xc0, 0x3c, 0x63, 0x0f, 0xbd, 0xb6, 0x34, 0xd3,
0xd2, 0xf5, 0xa0, 0x33, 0xc2, 0x19, 0x2f, 0xa2, 0xdc, 0xeb, 0xf4, 0x8d, 0x41, 0x97, 0x55, 0x90,
0xe2, 0x3c, 0xc3, 0x08, 0xe7, 0x82, 0xcf, 0xbc, 0xae, 0x8a, 0x53, 0x61, 0xf7, 0x00, 0xdc, 0x93,
0x38, 0xc3, 0xa0, 0x10, 0x38, 0x7e, 0x11, 0xa6, 0xe7, 0x28, 0xc2, 0x59, 0xe9, 0x39, 0x32, 0xc0,
0x0e, 0x0f, 0x9d, 0xf2, 0x08, 0x73, 0x4e, 0x67, 0x83, 0x0c, 0x55, 0x41, 0xd7, 0x87, 0xbd, 0xf1,
0x82, 0x0b, 0x9c, 0x8e, 0x31, 0x10, 0x98, 0x7b, 0x3d, 0xe9, 0xde, 0xb0, 0xd1, 0x9e, 0x27, 0x62,
0xce, 0xe3, 0xf0, 0x7b, 0x9e, 0x87, 0x49, 0xec, 0xed, 0xa9, 0x3d, 0x4d, 0x1b, 0x55, 0x89, 0x25,
0x11, 0x7a, 0x37, 0x54, 0x95, 0x68, 0xed, 0xff, 0x6a, 0x80, 0x33, 0xe2, 0xd9, 0x62, 0x92, 0x70,
0x31, 0xbd, 0x56, 0xad, 0xef, 0x82, 0x1d, 0x60, 0x14, 0x65, 0x9e, 0xd9, 0x37, 0x07, 0xbd, 0xc3,
0xdb, 0x07, 0x75, 0x13, 0xeb, 0x38, 0xc7, 0x18, 0x45, 0x4c, 0xed, 0x72, 0x3f, 0x02, 0x27, 0xc7,
0x65, 0x1a, 0xf1, 0x1c, 0x33, 0xcf, 0x92, 0x3f, 0x71, 0xd7, 0x3f, 0x79, 0xa6, 0x5d, 0x6c, 0xbd,
0x69, 0xeb, 0x2a, 0xf6, 0xf6, 0x55, 0xfc, 0x3f, 0x5b, 0x70, 0x63, 0xe3, 0x38, 0x77, 0x0f, 0x8c,
0x95, 0xcc, 0xdc, 0x66, 0xc6, 0x8a, 0x50, 0x29, 0xb3, 0xb6, 0x99, 0x51, 0x12, 0xba, 0x94, 0xdc,
0xb0, 0x99, 0x71, 0x49, 0x68, 0x21, 0x19, 0x61, 0x33, 0x63, 0xe1, 0xbe, 0x07, 0x9d, 0xef, 0x0a,
0x14, 0x21, 0x66, 0x9e, 0x2d, 0xb3, 0xfb, 0xdf, 0x3a, 0xbb, 0xa7, 0x05, 0x8a, 0x92, 0x55, 0x7e,
0xaa, 0x86, 0x64, 0x93, 0xa2, 0x86, 0x5c, 0x93, 0x2d, 0x27, 0xe6, 0x75, 0x94, 0x8d, 0xd6, 0xba,
0x8a, 0x8a, 0x0f, 0x54, 0xc5, 0x8f, 0xc1, 0xe2, 0x2b, 0xcc, 0x3c, 0x47, 0xc6, 0x7f, 0xeb, 0x25,
0x05, 0x3b, 0x18, 0xae, 0x30, 0xfb, 0x32, 0xce, 0x45, 0xc9, 0xe4, 0x76, 0xf7, 0x5d, 0x68, 0x07,
0x49, 0x94, 0x88, 0xcc, 0x83, 0xab, 0x89, 0x1d, 0x93, 0x9d, 0x69, 0xf7, 0x9d, 0xfb, 0xe0, 0xd4,
0xbf, 0x25, 0xfa, 0xbe, 0xc0, 0x52, 0x56, 0xc2, 0x61, 0xb4, 0x74, 0xdf, 0x06, 0xfb, 0x82, 0x47,
0x85, 0xea, 0x62, 0xef, 0xf0, 0xe6, 0x3a, 0xcc, 0x70, 0x15, 0x66, 0x4c, 0x39, 0x3f, 0x6d, 0x7d,
0x62, 0xf8, 0x73, 0xb0, 0x65, 0xe4, 0x06, 0x0f, 0x9c, 0x8a, 0x07, 0x72, 0xbe, 0x5a, 0x8d, 0xf9,
0xba, 0x05, 0xe6, 0x57, 0xb8, 0xd2, 0x23, 0x47, 0xcb, 0x9a, 0x2d, 0x56, 0x83, 0x2d, 0xfb, 0x60,
0x9f, 0xcb, 0xc3, 0x55, 0x17, 0x15, 0xf0, 0x7f, 0x31, 0xc0, 0xa2, 0xc3, 0xa9, 0xd7, 0x11, 0xce,
0x79, 0x50, 0x1e, 0x25, 0x45, 0x3c, 0xcd, 0x3c, 0xa3, 0x6f, 0x0e, 0x4c, 0xb6, 0x61, 0x73, 0x5f,
0x83, 0xf6, 0x44, 0x79, 0x5b, 0x7d, 0x73, 0xe0, 0x30, 0x8d, 0x28, 0x74, 0xc4, 0x27, 0x18, 0xe9,
0x14, 0x14, 0xa0, 0xdd, 0xa9, 0xc0, 0x59, 0xb8, 0xd2, 0x69, 0x68, 0x44, 0xf6, 0xac, 0x98, 0x91,
0x5d, 0x65, 0xa2, 0x11, 0x25, 0x3d, 0xe1, 0x59, 0xdd, 0x54, 0x5a, 0x53, 0xe4, 0x2c, 0xe0, 0x51,
0xd5, 0x55, 0x05, 0xfc, 0xdf, 0x0c, 0x9a, 0x76, 0xc5, 0xd2, 0xad, 0x0a, 0xbd, 0x0e, 0x5d, 0x62,
0xf0, 0xf3, 0x0b, 0x2e, 0x74, 0x95, 0x3a, 0x84, 0xcf, 0xb9, 0x70, 0x3f, 0x84, 0xb6, 0x2c, 0xf1,
0x8e, 0x89, 0xa9, 0xc2, 0xc9, 0xaa, 0x30, 0xbd, 0xad, 0xe6, 0x94, 0xd5, 0xe0, 0x54, 0x7d, 0x59,
0xbb, 0x79, 0xd9, 0xbb, 0x60, 0x13, 0x39, 0x4b, 0x99, 0xfd, 0xce, 0xc8, 0x8a, 0xc2, 0x6a, 0x97,
0x7f, 0x06, 0x37, 0x36, 0x4e, 0xac, 0x4f, 0x32, 0x36, 0x4f, 0x5a, 0xd3, 0xc5, 0xd1, 0xf4, 0x20,
0xa5, 0xcb, 0x30, 0xc2, 0x20, 0xc7, 0xa9, 0xac, 0x77, 0x97, 0xd5, 0xd8, 0xff, 0xc9, 0x58, 0xc7,
0x95, 0xe7, 0x91, 0x96, 0x05, 0xc9, 0x72, 0xc9, 0xe3, 0xa9, 0x0e, 0x5d, 0x41, 0xaa, 0xdb, 0x74,
0xa2, 0x43, 0xb7, 0xa6, 0x13, 0xc2, 0x22, 0xd5, 0x1d, 0x6c, 0x89, 0xd4, 0xed, 0x43, 0x6f, 0x89,
0x3c, 0x2b, 0x04, 0x2e, 0x31, 0xce, 0x75, 0x09, 0x9a, 0x26, 0xf7, 0x36, 0x74, 0x72, 0x3e, 0x7f,
0x4e, 0x24, 0xd7, 0x9d, 0xcc, 0xf9, 0xfc, 0x01, 0x96, 0xee, 0x1b, 0xe0, 0xcc, 0x42, 0x8c, 0xa6,
0xd2, 0xa5, 0xda, 0xd9, 0x95, 0x86, 0x07, 0x58, 0xfa, 0xbf, 0x1b, 0xd0, 0x1e, 0xa3, 0xb8, 0x40,
0x71, 0x2d, 0x91, 0x6b, 0x3e, 0x1e, 0xe6, 0x2b, 0x1e, 0x0f, 0x6b, 0xf7, 0xe3, 0x61, 0xaf, 0x1f,
0x8f, 0x7d, 0xb0, 0xc7, 0x22, 0x38, 0x19, 0xc9, 0x8c, 0x4c, 0xa6, 0x00, 0xb1, 0x71, 0x18, 0xe4,
0xe1, 0x05, 0xea, 0x17, 0x45, 0xa3, 0x2d, 0xed, 0xeb, 0xee, 0xd0, 0xbe, 0x1f, 0x0d, 0x68, 0x3f,
0xe4, 0x65, 0x52, 0xe4, 0x5b, 0x2c, 0xec, 0x43, 0x6f, 0x98, 0xa6, 0x51, 0x18, 0xa8, 0x5f, 0xab,
0x1b, 0x35, 0x4d, 0xb4, 0xe3, 0x51, 0xa3, 0xbe, 0xea, 0x6e, 0x4d, 0x13, 0xc9, 0xc5, 0xb1, 0xd4,
0x77, 0x25, 0xd6, 0x0d, 0xb9, 0x50, 0xb2, 0x2e, 0x9d, 0x54, 0x84, 0x61, 0x91, 0x27, 0xb3, 0x28,
0xb9, 0x94, 0xb7, 0xed, 0xb2, 0x1a, 0xfb, 0x7f, 0xb4, 0xc0, 0xfa, 0xaf, 0x34, 0x79, 0x0f, 0x8c,
0x50, 0x37, 0xdb, 0x08, 0x6b, 0x85, 0xee, 0x34, 0x14, 0xda, 0x83, 0x4e, 0x29, 0x78, 0x3c, 0xc7,
0xcc, 0xeb, 0x4a, 0x75, 0xa9, 0xa0, 0xf4, 0xc8, 0x39, 0x52, 0xd2, 0xec, 0xb0, 0x0a, 0xd6, 0x73,
0x01, 0x8d, 0xb9, 0xf8, 0x40, 0xab, 0x78, 0x4f, 0x66, 0xe4, 0x6d, 0x96, 0xe5, 0xaa, 0x78, 0xff,
0x7b, 0x9a, 0xfc, 0xb7, 0x01, 0x76, 0x3d, 0x54, 0xc7, 0x9b, 0x43, 0x75, 0xbc, 0x1e, 0xaa, 0xd1,
0x51, 0x35, 0x54, 0xa3, 0x23, 0xc2, 0xec, 0xb4, 0x1a, 0x2a, 0x76, 0x4a, 0xcd, 0xba, 0x2f, 0x92,
0x22, 0x3d, 0x2a, 0x55, 0x57, 0x1d, 0x56, 0x63, 0x62, 0xe2, 0x37, 0x0b, 0x14, 0xba, 0xd4, 0x0e,
0xd3, 0x88, 0x78, 0xfb, 0x50, 0x0a, 0x8e, 0x2a, 0xae, 0x02, 0xee, 0x3b, 0x60, 0x33, 0x2a, 0x9e,
0xac, 0xf0, 0x46, 0x5f, 0xa4, 0x99, 0x29, 0x2f, 0x05, 0x55, 0x5f, 0x6f, 0x9a, 0xc0, 0xd5, 0xb7,
0xdc, 0xfb, 0xd0, 0x1e, 0x2f, 0xc2, 0x59, 0x5e, 0xbd, 0x85, 0xff, 0x6f, 0x08, 0x56, 0xb8, 0x44,
0xe9, 0x63, 0x7a, 0x8b, 0xff, 0x14, 0x9c, 0xda, 0xb8, 0x4e, 0xc7, 0x68, 0xa6, 0xe3, 0x82, 0x75,
0x16, 0x87, 0x79, 0x35, 0xba, 0xb4, 0xa6, 0xcb, 0x3e, 0x2d, 0x78, 0x9c, 0x87, 0x79, 0x59, 0x8d,
0x6e, 0x85, 0xfd, 0x7b, 0x3a, 0x7d, 0x0a, 0x77, 0x96, 0xa6, 0x28, 0xb4, 0x0c, 0x28, 0x20, 0x0f,
0x49, 0x2e, 0x51, 0x29, 0xb8, 0xc9, 0x14, 0xf0, 0xbf, 0x05, 0x67, 0x18, 0xa1, 0xc8, 0x59, 0x11,
0xe1, 0xae, 0x97, 0xf1, 0xeb, 0xf1, 0x93, 0xc7, 0x55, 0x06, 0xb4, 0x5e, 0x8f, 0xbc, 0x79, 0x65,
0xe4, 0x1f, 0xf0, 0x94, 0x9f, 0x8c, 0x24, 0xcf, 0x4d, 0xa6, 0x91, 0xff, 0xb3, 0x01, 0x16, 0x69,
0x4b, 0x23, 0xb4, 0xf5, 0x2a, 0x5d, 0x3a, 0x15, 0xc9, 0x45, 0x38, 0x45, 0x51, 0x5d, 0xae, 0xc2,
0xb2, 0xe8, 0xc1, 0x02, 0xeb, 0x07, 0x58, 0x23, 0xe2, 0x1a, 0x7d, 0xea, 0x55, 0xb3, 0xd4, 0xe0,
0x1a, 0x99, 0x99, 0x72, 0xba, 0x6f, 0x02, 0x8c, 0x8b, 0x14, 0xc5, 0x70, 0xba, 0x0c, 0x63, 0xd9,
0xf4, 0x2e, 0x6b, 0x58, 0xfc, 0x2f, 0xd4, 0xc7, 0xe3, 0x96, 0x42, 0x19, 0xbb, 0x3f, 0x34, 0xaf,
0x66, 0xee, 0xff, 0x60, 0x40, 0xe7, 0x11, 0x4f, 0xd3, 0x30, 0x9e, 0x6f, 0xdc, 0xc2, 0x78, 0xe9,
0x2d, 0x5a, 0x1b, 0xb7, 0xd8, 0x07, 0x5b, 0x72, 0xb6, 0x7a, 0xed, 0x25, 0xd0, 0x35, 0xb3, 0xea,
0x76, 0x5c, 0xe7, 0xdb, 0x31, 0xda, 0xdc, 0xb3, 0xab, 0xa5, 0x5b, 0x75, 0xef, 0x43, 0x4f, 0x7f,
0xf3, 0xcb, 0x2f, 0x68, 0x2d, 0x9b, 0x0d, 0x13, 0xe5, 0x7d, 0x5a, 0x4c, 0xa2, 0x30, 0x90, 0xd9,
0x74, 0x99, 0x46, 0xfe, 0x21, 0xb4, 0x8f, 0x93, 0x78, 0x16, 0xce, 0xdd, 0x01, 0x58, 0xc3, 0x22,
0x5f, 0xc8, 0x93, 0x7a, 0x87, 0xfb, 0x8d, 0x91, 0x2f, 0xf2, 0x85, 0xda, 0xc3, 0xe4, 0x0e, 0xff,
0x33, 0x80, 0xb5, 0x8d, 0xfe, 0x48, 0xac, 0xfb, 0xf0, 0x18, 0x2f, 0x89, 0x2c, 0x99, 0x8c, 0xd2,
0x65, 0x3b, 0x3c, 0xfe, 0xe7, 0xe0, 0x1c, 0x15, 0x61, 0x34, 0x3d, 0x89, 0x67, 0x09, 0x89, 0xc6,
0x39, 0x8a, 0x6c, 0xdd, 0xa9, 0x0a, 0x52, 0xc2, 0xa4, 0x1f, 0xf5, 0xf4, 0x68, 0x34, 0x69, 0xcb,
0xff, 0x62, 0xf7, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x82, 0x96, 0xb8, 0xb3, 0x9d, 0x0d, 0x00,
0x00,
}

View File

@ -161,7 +161,8 @@ message Mapping {
string Provider = 1; // Provider is the provider that certifies and issues this user's authentication, e.g. GitHub
string Scheme = 2; // Scheme is the scheme used to perform this user's authentication, e.g. OAuth2 or LDAP
string Group = 3; // Group is the group or organizations that you are a part of in an auth provider
string GrantedRole = 4; // GrantedRole is the name of the role that you will be granted if you match the mapping
string ID = 4; // ID is the unique ID for the mapping
string Organization = 5; // Organization is the organization ID that resource belongs to
}
message Organization {
@ -169,7 +170,6 @@ message Organization {
string Name = 2; // Name is the organization's name
string DefaultRole = 3; // DefaultRole is the name of the role that is the default for any users added to the organization
bool Public = 4; // Public specifies that users must be explicitly added to the organization
repeated Mapping Mappings = 5; // Mappings is set of mappings a organization has
}
message Config {

128
bolt/mapping.go Normal file
View File

@ -0,0 +1,128 @@
package bolt
import (
"context"
"fmt"
"github.com/boltdb/bolt"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/bolt/internal"
)
// Ensure MappingsStore implements chronograf.MappingsStore.
var _ chronograf.MappingsStore = &MappingsStore{}
var (
// MappingsBucket is the bucket where organizations are stored.
MappingsBucket = []byte("MappingsV1")
)
// MappingsStore uses bolt to store and retrieve Mappings
type MappingsStore struct {
client *Client
}
// Migrate sets the default organization at runtime
func (s *MappingsStore) Migrate(ctx context.Context) error {
return nil
}
// Add creates a new Mapping in the MappingsStore
func (s *MappingsStore) Add(ctx context.Context, o *chronograf.Mapping) (*chronograf.Mapping, error) {
err := s.client.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket(MappingsBucket)
seq, err := b.NextSequence()
if err != nil {
return err
}
o.ID = fmt.Sprintf("%d", seq)
v, err := internal.MarshalMapping(o)
if err != nil {
return err
}
return b.Put([]byte(o.ID), v)
})
if err != nil {
return nil, err
}
return o, nil
}
// All returns all known organizations
func (s *MappingsStore) All(ctx context.Context) ([]chronograf.Mapping, error) {
var orgs []chronograf.Mapping
err := s.each(ctx, func(o *chronograf.Mapping) {
orgs = append(orgs, *o)
})
if err != nil {
return nil, err
}
return orgs, nil
}
// Delete the organization from MappingsStore
func (s *MappingsStore) Delete(ctx context.Context, o *chronograf.Mapping) error {
_, err := s.get(ctx, o.ID)
if err != nil {
return err
}
if err := s.client.db.Update(func(tx *bolt.Tx) error {
return tx.Bucket(MappingsBucket).Delete([]byte(o.ID))
}); err != nil {
return err
}
return nil
}
func (s *MappingsStore) get(ctx context.Context, id string) (*chronograf.Mapping, error) {
var o chronograf.Mapping
err := s.client.db.View(func(tx *bolt.Tx) error {
v := tx.Bucket(MappingsBucket).Get([]byte(id))
if v == nil {
return chronograf.ErrMappingNotFound
}
return internal.UnmarshalMapping(v, &o)
})
if err != nil {
return nil, err
}
return &o, nil
}
func (s *MappingsStore) each(ctx context.Context, fn func(*chronograf.Mapping)) error {
return s.client.db.View(func(tx *bolt.Tx) error {
return tx.Bucket(MappingsBucket).ForEach(func(k, v []byte) error {
var org chronograf.Mapping
if err := internal.UnmarshalMapping(v, &org); err != nil {
return err
}
fn(&org)
return nil
})
})
}
// Get returns a Mapping if the id exists.
func (s *MappingsStore) Get(ctx context.Context, id string) (*chronograf.Mapping, error) {
return s.get(ctx, id)
}
// Update the organization in MappingsStore
func (s *MappingsStore) Update(ctx context.Context, o *chronograf.Mapping) error {
return s.client.db.Update(func(tx *bolt.Tx) error {
if v, err := internal.MarshalMapping(o); err != nil {
return err
} else if err := tx.Bucket(MappingsBucket).Put([]byte(o.ID), v); err != nil {
return err
}
return nil
})
}

489
bolt/mapping_test.go Normal file
View File

@ -0,0 +1,489 @@
package bolt_test
import (
"context"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/influxdata/chronograf"
)
var mappingCmpOptions = cmp.Options{
cmpopts.IgnoreFields(chronograf.Mapping{}, "ID"),
cmpopts.EquateEmpty(),
}
func TestMappingStore_Add(t *testing.T) {
type fields struct {
mappings []*chronograf.Mapping
}
type args struct {
mapping *chronograf.Mapping
}
type wants struct {
mapping *chronograf.Mapping
err error
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "default with wildcards",
args: args{
mapping: &chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
},
wants: wants{
mapping: &chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
},
},
{
name: "simple",
args: args{
mapping: &chronograf.Mapping{
Organization: "default",
Provider: "github",
Scheme: "oauth2",
Group: "idk",
},
},
wants: wants{
mapping: &chronograf.Mapping{
Organization: "default",
Provider: "github",
Scheme: "oauth2",
Group: "idk",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewTestClient()
if err != nil {
t.Fatal(err)
}
defer client.Close()
s := client.MappingsStore
ctx := context.Background()
for _, mapping := range tt.fields.mappings {
// YOLO database prepopulation
_, _ = s.Add(ctx, mapping)
}
tt.args.mapping, err = s.Add(ctx, tt.args.mapping)
if (err != nil) != (tt.wants.err != nil) {
t.Errorf("MappingsStore.Add() error = %v, want error %v", err, tt.wants.err)
return
}
got, err := s.Get(ctx, tt.args.mapping.ID)
if err != nil {
t.Fatalf("failed to get mapping: %v", err)
return
}
if diff := cmp.Diff(got, tt.wants.mapping, mappingCmpOptions...); diff != "" {
t.Errorf("MappingStore.Add():\n-got/+want\ndiff %s", diff)
return
}
})
}
}
func TestMappingStore_All(t *testing.T) {
type fields struct {
mappings []*chronograf.Mapping
}
type args struct {
}
type wants struct {
mappings []chronograf.Mapping
err error
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "simple",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
wants: wants{
mappings: []chronograf.Mapping{
chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewTestClient()
if err != nil {
t.Fatal(err)
}
defer client.Close()
s := client.MappingsStore
ctx := context.Background()
for _, mapping := range tt.fields.mappings {
// YOLO database prepopulation
_, _ = s.Add(ctx, mapping)
}
got, err := s.All(ctx)
if (err != nil) != (tt.wants.err != nil) {
t.Errorf("MappingsStore.All() error = %v, want error %v", err, tt.wants.err)
return
}
if diff := cmp.Diff(got, tt.wants.mappings, mappingCmpOptions...); diff != "" {
t.Errorf("MappingStore.All():\n-got/+want\ndiff %s", diff)
return
}
})
}
}
func TestMappingStore_Delete(t *testing.T) {
type fields struct {
mappings []*chronograf.Mapping
}
type args struct {
mapping *chronograf.Mapping
}
type wants struct {
err error
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "simple",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
args: args{
mapping: &chronograf.Mapping{
ID: "1",
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
},
wants: wants{
err: nil,
},
},
{
name: "mapping not found",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
args: args{
mapping: &chronograf.Mapping{
ID: "0",
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
},
wants: wants{
err: chronograf.ErrMappingNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewTestClient()
if err != nil {
t.Fatal(err)
}
defer client.Close()
s := client.MappingsStore
ctx := context.Background()
for _, mapping := range tt.fields.mappings {
// YOLO database prepopulation
_, _ = s.Add(ctx, mapping)
}
err = s.Delete(ctx, tt.args.mapping)
if (err != nil) != (tt.wants.err != nil) {
t.Errorf("MappingsStore.Delete() error = %v, want error %v", err, tt.wants.err)
return
}
})
}
}
func TestMappingStore_Get(t *testing.T) {
type fields struct {
mappings []*chronograf.Mapping
}
type args struct {
mappingID string
}
type wants struct {
mapping *chronograf.Mapping
err error
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "simple",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
args: args{
mappingID: "1",
},
wants: wants{
mapping: &chronograf.Mapping{
ID: "1",
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
err: nil,
},
},
{
name: "mapping not found",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
args: args{
mappingID: "0",
},
wants: wants{
err: chronograf.ErrMappingNotFound,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewTestClient()
if err != nil {
t.Fatal(err)
}
defer client.Close()
s := client.MappingsStore
ctx := context.Background()
for _, mapping := range tt.fields.mappings {
// YOLO database prepopulation
_, _ = s.Add(ctx, mapping)
}
got, err := s.Get(ctx, tt.args.mappingID)
if (err != nil) != (tt.wants.err != nil) {
t.Errorf("MappingsStore.Get() error = %v, want error %v", err, tt.wants.err)
return
}
if diff := cmp.Diff(got, tt.wants.mapping, mappingCmpOptions...); diff != "" {
t.Errorf("MappingStore.Get():\n-got/+want\ndiff %s", diff)
return
}
})
}
}
func TestMappingStore_Update(t *testing.T) {
type fields struct {
mappings []*chronograf.Mapping
}
type args struct {
mapping *chronograf.Mapping
}
type wants struct {
mapping *chronograf.Mapping
err error
}
tests := []struct {
name string
fields fields
args args
wants wants
}{
{
name: "simple",
fields: fields{
mappings: []*chronograf.Mapping{
&chronograf.Mapping{
Organization: "default",
Provider: "*",
Scheme: "*",
Group: "*",
},
&chronograf.Mapping{
Organization: "0",
Provider: "google",
Scheme: "ldap",
Group: "*",
},
},
},
args: args{
mapping: &chronograf.Mapping{
ID: "1",
Organization: "default",
Provider: "cool",
Scheme: "it",
Group: "works",
},
},
wants: wants{
mapping: &chronograf.Mapping{
ID: "1",
Organization: "default",
Provider: "cool",
Scheme: "it",
Group: "works",
},
err: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client, err := NewTestClient()
if err != nil {
t.Fatal(err)
}
defer client.Close()
s := client.MappingsStore
ctx := context.Background()
for _, mapping := range tt.fields.mappings {
// YOLO database prepopulation
_, _ = s.Add(ctx, mapping)
}
err = s.Update(ctx, tt.args.mapping)
if (err != nil) != (tt.wants.err != nil) {
t.Errorf("MappingsStore.Update() error = %v, want error %v", err, tt.wants.err)
return
}
if diff := cmp.Diff(tt.args.mapping, tt.wants.mapping, mappingCmpOptions...); diff != "" {
t.Errorf("MappingStore.Update():\n-got/+want\ndiff %s", diff)
return
}
})
}
}

View File

@ -29,14 +29,6 @@ const (
DefaultOrganizationPublic bool = true
)
// DefaultOrganizationMapping is the mapping for the default organization
var DefaultOrganizationMapping = chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: DefaultOrganizationRole,
}
// OrganizationsStore uses bolt to store and retrieve Organizations
type OrganizationsStore struct {
client *Client
@ -54,9 +46,14 @@ func (s *OrganizationsStore) CreateDefault(ctx context.Context) error {
Name: DefaultOrganizationName,
DefaultRole: DefaultOrganizationRole,
Public: DefaultOrganizationPublic,
Mappings: []chronograf.Mapping{
DefaultOrganizationMapping,
},
}
m := chronograf.Mapping{
ID: string(DefaultOrganizationID),
Organization: string(DefaultOrganizationID),
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
}
return s.client.db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket(OrganizationsBucket)
@ -70,6 +67,17 @@ func (s *OrganizationsStore) CreateDefault(ctx context.Context) error {
return err
}
b = tx.Bucket(MappingsBucket)
v = b.Get(DefaultOrganizationID)
if v != nil {
return nil
}
if v, err := internal.MarshalMapping(&m); err != nil {
return err
} else if err := b.Put(DefaultOrganizationID, v); err != nil {
return err
}
return nil
})
}

View File

@ -42,26 +42,10 @@ func TestOrganizationsStore_GetWithName(t *testing.T) {
ctx: context.Background(),
org: &chronograf.Organization{
Name: "EE - Evil Empire",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
want: &chronograf.Organization{
Name: "EE - Evil Empire",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
addFirst: true,
},
@ -187,9 +171,6 @@ func TestOrganizationsStore_All(t *testing.T) {
Name: "EE - Evil Empire",
DefaultRole: roles.MemberRoleName,
Public: true,
Mappings: []chronograf.Mapping{
bolt.DefaultOrganizationMapping,
},
},
{
Name: "The Good Place",
@ -203,9 +184,6 @@ func TestOrganizationsStore_All(t *testing.T) {
Name: "EE - Evil Empire",
DefaultRole: roles.MemberRoleName,
Public: true,
Mappings: []chronograf.Mapping{
bolt.DefaultOrganizationMapping,
},
},
{
Name: "The Good Place",
@ -216,9 +194,6 @@ func TestOrganizationsStore_All(t *testing.T) {
Name: bolt.DefaultOrganizationName,
DefaultRole: bolt.DefaultOrganizationRole,
Public: bolt.DefaultOrganizationPublic,
Mappings: []chronograf.Mapping{
bolt.DefaultOrganizationMapping,
},
},
},
addFirst: true,
@ -260,10 +235,9 @@ func TestOrganizationsStore_Update(t *testing.T) {
orgs []chronograf.Organization
}
type args struct {
ctx context.Context
initial *chronograf.Organization
updates *chronograf.Organization
mappings []chronograf.Mapping
ctx context.Context
initial *chronograf.Organization
updates *chronograf.Organization
}
tests := []struct {
name string
@ -387,7 +361,7 @@ func TestOrganizationsStore_Update(t *testing.T) {
addFirst: true,
},
{
name: "Update organization name and mappings",
name: "Update organization name",
fields: fields{},
args: args{
ctx: context.Background(),
@ -397,26 +371,10 @@ func TestOrganizationsStore_Update(t *testing.T) {
},
updates: &chronograf.Organization{
Name: "The Bad Place",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
want: &chronograf.Organization{
Name: "The Bad Place",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
addFirst: true,
},
@ -468,9 +426,6 @@ func TestOrganizationsStore_Update(t *testing.T) {
if tt.args.updates.DefaultRole != "" {
tt.args.initial.DefaultRole = tt.args.updates.DefaultRole
}
if tt.args.updates.Mappings != nil {
tt.args.initial.Mappings = tt.args.updates.Mappings
}
if tt.args.updates.Public != tt.args.initial.Public {
tt.args.initial.Public = tt.args.updates.Public
@ -682,9 +637,6 @@ func TestOrganizationsStore_DefaultOrganization(t *testing.T) {
Name: bolt.DefaultOrganizationName,
DefaultRole: bolt.DefaultOrganizationRole,
Public: bolt.DefaultOrganizationPublic,
Mappings: []chronograf.Mapping{
bolt.DefaultOrganizationMapping,
},
},
wantErr: false,
},

View File

@ -27,6 +27,7 @@ const (
ErrInvalidColor = Error("Invalid color. Accepted color format is #RRGGBB")
ErrUserAlreadyExists = Error("user already exists")
ErrOrganizationNotFound = Error("organization not found")
ErrMappingNotFound = Error("mapping not found")
ErrOrganizationAlreadyExists = Error("organization already exists")
ErrCannotDeleteDefaultOrganization = Error("cannot delete default organization")
ErrConfigNotFound = Error("cannot find configuration")
@ -563,18 +564,6 @@ type LayoutsStore interface {
Update(context.Context, Layout) error
}
// Organization is a group of resources under a common name
type Organization struct {
ID string `json:"id"`
Name string `json:"name"`
// DefaultRole is the name of the role that is the default for any users added to the organization
DefaultRole string `json:"defaultRole,omitempty"`
// Public specifies whether users must be explicitly added to the organization.
// It is currently only used by the default organization, but that may change in the future.
Public bool `json:"public"`
Mappings []Mapping `json:"mappings"`
}
// MappingWildcard is the wildcard value for mappings
const MappingWildcard string = "*"
@ -584,19 +573,47 @@ const MappingWildcard string = "*"
// explicit role within the organization.
//
// One can think of a mapping like so:
// Provider:Scheme:Group -> GrantedRole
// github:oauth2:influxdata -> Viewer
// beyondcorp:ldap:influxdata -> Admin
// Provider:Scheme:Group -> Organization
// github:oauth2:influxdata -> Happy
// beyondcorp:ldap:influxdata -> TheBillHilliettas
//
// Any of Provider, Scheme, or Group may be provided as a wildcard *
// github:oauth2:* -> Editor
// *:*:* -> Member
// github:oauth2:* -> MyOrg
// *:*:* -> AllOrg
type Mapping struct {
ID string `json:"id"`
Organization string `json:"organization"`
Provider string `json:"provider"`
Scheme string `json:"scheme"`
Group string `json:"group"`
}
GrantedRole string `json:"grantedRole"`
// MappingsStore is the storage and retrieval of Mappings
type MappingsStore interface {
// Add creates a new Mapping.
// The Created mapping is returned back to the user with the
// ID field populated.
Add(context.Context, *Mapping) (*Mapping, error)
// All lists all Mapping in the MappingsStore
All(context.Context) ([]Mapping, error)
// Delete removes an Mapping from the MappingsStore
Delete(context.Context, *Mapping) error
// Get retrieves an Mapping from the MappingsStore
Get(context.Context, string) (*Mapping, error)
// Update updates an Mapping in the MappingsStore
Update(context.Context, *Mapping) error
}
// Organization is a group of resources under a common name
type Organization struct {
ID string `json:"id"`
Name string `json:"name"`
// DefaultRole is the name of the role that is the default for any users added to the organization
DefaultRole string `json:"defaultRole,omitempty"`
// Public specifies whether users must be explicitly added to the organization.
// It is currently only used by the default organization, but that may change in the future.
Public bool `json:"public"`
}
// OrganizationQuery represents the attributes that a organization may be retrieved by.

View File

@ -26,6 +26,7 @@ import (
func TestServer(t *testing.T) {
type fields struct {
Organizations []chronograf.Organization
Mappings []chronograf.Mapping
Users []chronograf.User
Sources []chronograf.Source
Servers []chronograf.Server
@ -351,15 +352,7 @@ func TestServer(t *testing.T) {
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "member"
}
]
"public": true
},
{
"links": {
@ -368,9 +361,7 @@ func TestServer(t *testing.T) {
"id": "howdy",
"name": "An Organization",
"defaultRole": "viewer",
"public": false,
"mappings": [
]
"public": false
}
]
}`,
@ -419,9 +410,7 @@ func TestServer(t *testing.T) {
"id": "howdy",
"name": "An Organization",
"defaultRole": "viewer",
"public": false,
"mappings": [
]
"public": false
}`,
},
},
@ -1303,201 +1292,6 @@ func TestServer(t *testing.T) {
"code": 401,
"message": "user cannot modify their own SuperAdmin status"
}
`,
},
},
{
name: "GET /me",
subName: "New user hits me for the first time",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "influxdata",
GrantedRole: roles.AdminRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "mimi",
GrantedRole: roles.ViewerRoleName,
},
},
},
{
ID: "2",
Name: "What",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "mimi",
GrantedRole: roles.ViewerRoleName,
},
},
},
{
ID: "3",
Name: "Okay",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{},
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/me",
principal: oauth2.Principal{
Subject: "billietta",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "2",
"name": "billietta",
"roles": [
{
"name": "admin",
"organization": "1"
},
{
"name": "viewer",
"organization": "2"
},
{
"name": "member",
"organization": "default"
}
],
"provider": "github",
"scheme": "oauth2",
"links": {
"self": "/chronograf/v1/users/2"
},
"organizations": [
{
"id": "1",
"name": "Sweet",
"defaultRole": "viewer",
"public": false,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "editor"
},
{
"provider": "github",
"scheme": "*",
"group": "influxdata",
"grantedRole": "admin"
},
{
"provider": "github",
"scheme": "*",
"group": "mimi",
"grantedRole": "viewer"
}
]
},
{
"id": "2",
"name": "What",
"defaultRole": "viewer",
"public": false,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "member"
},
{
"provider": "github",
"scheme": "*",
"group": "mimi",
"grantedRole": "viewer"
}
]
},
{
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "member"
}
]
}
],
"currentOrganization": {
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "member"
}
]
}
}
`,
},
},
@ -1576,32 +1370,20 @@ func TestServer(t *testing.T) {
"id": "1",
"name": "Sweet",
"defaultRole": "viewer",
"public": false,
"mappings": [
]
"public": false
},
{
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true,
"mappings": [
{
"provider": "*",
"scheme": "*",
"group": "*",
"grantedRole": "member"
}
]
"public": true
}
],
"currentOrganization": {
"id": "1",
"name": "Sweet",
"defaultRole": "viewer",
"public": false,
"mappings": [
]
"public": false
}
}`,
},
@ -1663,6 +1445,141 @@ func TestServer(t *testing.T) {
}`,
},
},
{
name: "GET /me",
subName: "New user hits me for the first time",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
Group: "influxdata",
},
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
Group: "*",
},
{
ID: "2",
Organization: "2",
Provider: "github",
Scheme: "*",
Group: "*",
},
{
ID: "3",
Organization: "3",
Provider: "auth0",
Scheme: "ldap",
Group: "*",
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
{
ID: "2",
Name: "What",
DefaultRole: roles.EditorRoleName,
},
{
ID: "3",
Name: "Okay",
DefaultRole: roles.AdminRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/me",
principal: oauth2.Principal{
Subject: "billietta",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "2",
"name": "billietta",
"roles": [
{
"name": "viewer",
"organization": "1"
},
{
"name": "editor",
"organization": "2"
},
{
"name": "member",
"organization": "default"
}
],
"provider": "github",
"scheme": "oauth2",
"links": {
"self": "/chronograf/v1/users/2"
},
"organizations": [
{
"id": "1",
"name": "Sweet",
"defaultRole": "viewer",
"public": false
},
{
"id": "2",
"name": "What",
"defaultRole": "editor",
"public": false
},
{
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true
}
],
"currentOrganization": {
"id": "default",
"name": "Default",
"defaultRole": "member",
"public": true
}
}
`,
},
},
}
for _, tt := range tests {
@ -1702,6 +1619,16 @@ func TestServer(t *testing.T) {
}
}
// Populate Organizations
for i, mapping := range tt.fields.Mappings {
o, err := boltdb.MappingsStore.Add(ctx, &mapping)
if err != nil {
t.Fatalf("failed to add mapping: %v", err)
return
}
tt.fields.Mappings[i] = *o
}
// Populate Organizations
for i, organization := range tt.fields.Organizations {
o, err := boltdb.OrganizationsStore.Add(ctx, &organization)

35
mocks/mapping.go Normal file
View File

@ -0,0 +1,35 @@
package mocks
import (
"context"
"github.com/influxdata/chronograf"
)
type MappingsStore struct {
AddF func(context.Context, *chronograf.Mapping) (*chronograf.Mapping, error)
AllF func(context.Context) ([]chronograf.Mapping, error)
DeleteF func(context.Context, *chronograf.Mapping) error
UpdateF func(context.Context, *chronograf.Mapping) error
GetF func(context.Context, string) (*chronograf.Mapping, error)
}
func (s *MappingsStore) Add(ctx context.Context, m *chronograf.Mapping) (*chronograf.Mapping, error) {
return s.AddF(ctx, m)
}
func (s *MappingsStore) All(ctx context.Context) ([]chronograf.Mapping, error) {
return s.AllF(ctx)
}
func (s *MappingsStore) Delete(ctx context.Context, m *chronograf.Mapping) error {
return s.DeleteF(ctx, m)
}
func (s *MappingsStore) Get(ctx context.Context, id string) (*chronograf.Mapping, error) {
return s.GetF(ctx, id)
}
func (s *MappingsStore) Update(ctx context.Context, m *chronograf.Mapping) error {
return s.UpdateF(ctx, m)
}

View File

@ -9,6 +9,7 @@ import (
// Store is a server.DataStore
type Store struct {
SourcesStore chronograf.SourcesStore
MappingsStore chronograf.MappingsStore
ServersStore chronograf.ServersStore
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
@ -36,6 +37,9 @@ func (s *Store) Users(ctx context.Context) chronograf.UsersStore {
func (s *Store) Organizations(ctx context.Context) chronograf.OrganizationsStore {
return s.OrganizationsStore
}
func (s *Store) Mappings(ctx context.Context) chronograf.MappingsStore {
return s.MappingsStore
}
func (s *Store) Dashboards(ctx context.Context) chronograf.DashboardsStore {
return s.DashboardsStore

33
noop/mappings.go Normal file
View File

@ -0,0 +1,33 @@
package noop
import (
"context"
"fmt"
"github.com/influxdata/chronograf"
)
// ensure MappingsStore implements chronograf.MappingsStore
var _ chronograf.MappingsStore = &MappingsStore{}
type MappingsStore struct{}
func (s *MappingsStore) All(context.Context) ([]chronograf.Mapping, error) {
return nil, fmt.Errorf("no mappings found")
}
func (s *MappingsStore) Add(context.Context, *chronograf.Mapping) (*chronograf.Mapping, error) {
return nil, fmt.Errorf("failed to add mapping")
}
func (s *MappingsStore) Delete(context.Context, *chronograf.Mapping) error {
return fmt.Errorf("failed to delete mapping")
}
func (s *MappingsStore) Get(ctx context.Context, ID string) (*chronograf.Mapping, error) {
return nil, chronograf.ErrMappingNotFound
}
func (s *MappingsStore) Update(context.Context, *chronograf.Mapping) error {
return fmt.Errorf("failed to update mapping")
}

View File

@ -1,56 +1,61 @@
package server
import (
"context"
"fmt"
"strings"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/roles"
)
func MappedRole(o chronograf.Organization, p oauth2.Principal) *chronograf.Role {
roles := []*chronograf.Role{}
for _, mapping := range o.Mappings {
role := applyMapping(mapping, p)
if role != nil {
role.Organization = o.ID
roles = append(roles, role)
func (s *Service) mapPrincipalToRoles(ctx context.Context, p oauth2.Principal) ([]chronograf.Role, error) {
mappings, err := s.Store.Mappings(ctx).All(ctx)
if err != nil {
return nil, err
}
roles := []chronograf.Role{}
MappingsLoop:
for _, mapping := range mappings {
if applyMapping(mapping, p) {
org, err := s.Store.Organizations(ctx).Get(ctx, chronograf.OrganizationQuery{ID: &mapping.Organization})
if err != nil {
return nil, err
}
for _, role := range roles {
if role.Organization == org.ID {
continue MappingsLoop
}
}
roles = append(roles, chronograf.Role{Organization: org.ID, Name: org.DefaultRole})
}
}
fmt.Println("Here 2")
return maxRole(roles)
return roles, nil
}
func applyMapping(m chronograf.Mapping, p oauth2.Principal) *chronograf.Role {
func applyMapping(m chronograf.Mapping, p oauth2.Principal) bool {
switch m.Provider {
case chronograf.MappingWildcard, p.Issuer:
default:
return nil
return false
}
switch m.Scheme {
case chronograf.MappingWildcard, "oauth2":
default:
return nil
return false
}
if m.Group == chronograf.MappingWildcard {
return &chronograf.Role{
Name: m.GrantedRole,
}
return true
}
groups := strings.Split(p.Group, ",")
match := matchGroup(m.Group, groups)
if match {
return &chronograf.Role{
Name: m.GrantedRole,
}
}
return nil
return matchGroup(m.Group, groups)
}
func matchGroup(match string, groups []string) bool {
@ -63,49 +68,21 @@ func matchGroup(match string, groups []string) bool {
return false
}
func maxRole(roles []*chronograf.Role) *chronograf.Role {
var max *chronograf.Role
for _, role := range roles {
max = maximumRole(max, role)
}
return max
}
func maximumRole(r1, r2 *chronograf.Role) *chronograf.Role {
if r1 == nil {
return r2
}
if r2 == nil {
return r2
}
if r1.Name == roles.AdminRoleName {
return r1
}
if r2.Name == roles.AdminRoleName {
return r2
}
if r1.Name == roles.EditorRoleName {
return r1
}
if r2.Name == roles.EditorRoleName {
return r2
}
if r1.Name == roles.ViewerRoleName {
return r1
}
if r2.Name == roles.ViewerRoleName {
return r2
}
if r1.Name == roles.MemberRoleName {
return r1
}
if r2.Name == roles.MemberRoleName {
return r2
}
return nil
}
//func (r *organizationRequest) ValidMappings() error {
// for _, m := range r.Mappings {
// if m.Provider == "" {
// return fmt.Errorf("mapping must specify provider")
// }
// if m.Scheme == "" {
// return fmt.Errorf("mapping must specify scheme")
// }
// if m.Group == "" {
// return fmt.Errorf("mapping must specify group")
// }
// if m.GrantedRole == "" {
// return fmt.Errorf("mapping must specify grantedRole")
// }
// }
//
// return nil
//}

View File

@ -1,391 +1,381 @@
package server_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/roles"
"github.com/influxdata/chronograf/server"
)
func TestMappedRole(t *testing.T) {
type args struct {
org chronograf.Organization
principal oauth2.Principal
}
type wants struct {
role *chronograf.Role
}
tests := []struct {
name string
args args
wants wants
}{
{
name: "single mapping all wildcards",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "two mapping all wildcards",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "two mapping all wildcards, different order",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "two mappings with explicit principal",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "oauth2",
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.MemberRoleName,
Organization: "cool",
},
},
},
{
name: "different two mapping all wildcards",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "different two mapping all wildcards, different ordering",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.ViewerRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping all wildcards",
args: args{
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping only one match",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "influxdata.com",
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "not_influxdata",
GrantedRole: roles.AdminRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.EditorRoleName,
Organization: "cool",
},
},
},
{
name: "three mapping only two matches",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: "influxdata.com",
GrantedRole: roles.AdminRoleName,
},
chronograf.Mapping{
Provider: "google",
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
{
name: "missing provider",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "google",
Group: "influxdata.com",
},
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "",
Scheme: "ldap",
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: nil,
},
},
{
name: "user is in multiple github groups",
args: args{
principal: oauth2.Principal{
Subject: "billieta@influxdata.com",
Issuer: "github",
Group: "influxdata,another,mimi",
},
org: chronograf.Organization{
ID: "cool",
Name: "Cool Org",
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "influxdata",
GrantedRole: roles.MemberRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "mimi",
GrantedRole: roles.EditorRoleName,
},
chronograf.Mapping{
Provider: "github",
Scheme: chronograf.MappingWildcard,
Group: "another",
GrantedRole: roles.AdminRoleName,
},
},
},
},
wants: wants{
role: &chronograf.Role{
Name: roles.AdminRoleName,
Organization: "cool",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
role := server.MappedRole(tt.args.org, tt.args.principal)
if diff := cmp.Diff(role, tt.wants.role); diff != "" {
t.Errorf("%q. MappedRole():\n-got/+want\ndiff %s", tt.name, diff)
}
})
}
}
//func TestMappedRole(t *testing.T) {
// type args struct {
// org chronograf.Organization
// principal oauth2.Principal
// }
// type wants struct {
// role *chronograf.Role
// }
//
// tests := []struct {
// name string
// args args
// wants wants
// }{
// {
// name: "single mapping all wildcards",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.ViewerRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "two mapping all wildcards",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.EditorRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.EditorRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "two mapping all wildcards, different order",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.EditorRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.EditorRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "two mappings with explicit principal",
// args: args{
// principal: oauth2.Principal{
// Subject: "billieta@influxdata.com",
// Issuer: "google",
// Group: "influxdata.com",
// },
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: "oauth2",
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.MemberRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.MemberRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.MemberRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "different two mapping all wildcards",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.MemberRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.ViewerRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "different two mapping all wildcards, different ordering",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.MemberRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.ViewerRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "three mapping all wildcards",
// args: args{
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.EditorRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.ViewerRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.AdminRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.AdminRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "three mapping only one match",
// args: args{
// principal: oauth2.Principal{
// Subject: "billieta@influxdata.com",
// Issuer: "google",
// Group: "influxdata.com",
// },
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: "google",
// Scheme: chronograf.MappingWildcard,
// Group: "influxdata.com",
// GrantedRole: roles.EditorRoleName,
// },
// chronograf.Mapping{
// Provider: "google",
// Scheme: chronograf.MappingWildcard,
// Group: "not_influxdata",
// GrantedRole: roles.AdminRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: "ldap",
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.AdminRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.EditorRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "three mapping only two matches",
// args: args{
// principal: oauth2.Principal{
// Subject: "billieta@influxdata.com",
// Issuer: "google",
// Group: "influxdata.com",
// },
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: "google",
// Scheme: chronograf.MappingWildcard,
// Group: "influxdata.com",
// GrantedRole: roles.AdminRoleName,
// },
// chronograf.Mapping{
// Provider: "google",
// Scheme: chronograf.MappingWildcard,
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.EditorRoleName,
// },
// chronograf.Mapping{
// Provider: chronograf.MappingWildcard,
// Scheme: "ldap",
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.AdminRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.AdminRoleName,
// Organization: "cool",
// },
// },
// },
// {
// name: "missing provider",
// args: args{
// principal: oauth2.Principal{
// Subject: "billieta@influxdata.com",
// Issuer: "google",
// Group: "influxdata.com",
// },
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: "",
// Scheme: "ldap",
// Group: chronograf.MappingWildcard,
// GrantedRole: roles.AdminRoleName,
// },
// },
// },
// },
// wants: wants{
// role: nil,
// },
// },
// {
// name: "user is in multiple github groups",
// args: args{
// principal: oauth2.Principal{
// Subject: "billieta@influxdata.com",
// Issuer: "github",
// Group: "influxdata,another,mimi",
// },
// org: chronograf.Organization{
// ID: "cool",
// Name: "Cool Org",
// Mappings: []chronograf.Mapping{
// chronograf.Mapping{
// Provider: "github",
// Scheme: chronograf.MappingWildcard,
// Group: "influxdata",
// GrantedRole: roles.MemberRoleName,
// },
// chronograf.Mapping{
// Provider: "github",
// Scheme: chronograf.MappingWildcard,
// Group: "mimi",
// GrantedRole: roles.EditorRoleName,
// },
// chronograf.Mapping{
// Provider: "github",
// Scheme: chronograf.MappingWildcard,
// Group: "another",
// GrantedRole: roles.AdminRoleName,
// },
// },
// },
// },
// wants: wants{
// role: &chronograf.Role{
// Name: roles.AdminRoleName,
// Organization: "cool",
// },
// },
// },
// }
//
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// role := server.MappedRole(tt.args.org, tt.args.principal)
//
// if diff := cmp.Diff(role, tt.wants.role); diff != "" {
// t.Errorf("%q. MappedRole():\n-got/+want\ndiff %s", tt.name, diff)
// }
// })
// }
//}

View File

@ -270,6 +270,7 @@ func (s *Service) Me(w http.ResponseWriter, r *http.Request) {
return
}
// TODO(desa) get rid of this
// If users must be explicitly added to the default organization, respond with 403
// forbidden
if !defaultOrg.Public {
@ -288,18 +289,11 @@ func (s *Service) Me(w http.ResponseWriter, r *http.Request) {
SuperAdmin: s.newUsersAreSuperAdmin(),
}
allOrgs, err := s.Store.Organizations(serverCtx).All(serverCtx)
roles, err := s.mapPrincipalToRoles(serverCtx, p)
if err != nil {
Error(w, http.StatusInternalServerError, err.Error(), s.Logger)
return
}
roles := []chronograf.Role{}
for _, org := range allOrgs {
role := MappedRole(org, p)
if role != nil {
roles = append(roles, *role)
}
}
user.Roles = roles

View File

@ -23,6 +23,7 @@ func TestService_Me(t *testing.T) {
type fields struct {
UsersStore chronograf.UsersStore
OrganizationsStore chronograf.OrganizationsStore
MappingsStore chronograf.MappingsStore
ConfigStore chronograf.ConfigStore
Logger chronograf.Logger
UseAuth bool
@ -56,6 +57,18 @@ func TestService_Me(t *testing.T) {
},
},
},
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{
{
Organization: "0",
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
},
}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -63,7 +76,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: false,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -74,14 +86,12 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: false,
Mappings: []chronograf.Mapping{},
}, nil
case "1":
return &chronograf.Organization{
ID: "1",
Name: "The Bad Place",
Public: false,
Mappings: []chronograf.Mapping{},
ID: "1",
Name: "The Bad Place",
Public: false,
}, nil
}
return nil, nil
@ -124,6 +134,11 @@ func TestService_Me(t *testing.T) {
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -131,7 +146,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: false,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -142,14 +156,12 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
case "1":
return &chronograf.Organization{
ID: "1",
Name: "The Bad Place",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "1",
Name: "The Bad Place",
Public: true,
}, nil
}
return nil, nil
@ -182,7 +194,7 @@ func TestService_Me(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"me","roles":[{"name":"viewer","organization":"0"}],"provider":"github","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
wantBody: `{"name":"me","roles":[{"name":"viewer","organization":"0"}],"provider":"github","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"viewer","public":true}],"currentOrganization":{"id":"0","name":"Default","defaultRole":"viewer","public":true}}`,
},
{
name: "Existing user - private default org",
@ -193,6 +205,11 @@ func TestService_Me(t *testing.T) {
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -200,7 +217,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: false,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -211,14 +227,12 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
case "1":
return &chronograf.Organization{
ID: "1",
Name: "The Bad Place",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "1",
Name: "The Bad Place",
Public: true,
}, nil
}
return nil, nil
@ -261,6 +275,11 @@ func TestService_Me(t *testing.T) {
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -268,7 +287,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -279,14 +297,12 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
case "1":
return &chronograf.Organization{
ID: "1",
Name: "The Bad Place",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "1",
Name: "The Bad Place",
Public: true,
}, nil
}
return nil, nil
@ -318,7 +334,7 @@ func TestService_Me(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"me","roles":[{"name":"viewer","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
wantBody: `{"name":"me","roles":[{"name":"viewer","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"viewer","public":true}],"currentOrganization":{"id":"0","name":"Default","defaultRole":"viewer","public":true}}`,
},
{
name: "Existing user - organization doesn't exist",
@ -329,6 +345,11 @@ func TestService_Me(t *testing.T) {
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -336,7 +357,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -347,7 +367,6 @@ func TestService_Me(t *testing.T) {
Name: "Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
}
return nil, chronograf.ErrOrganizationNotFound
@ -394,6 +413,18 @@ func TestService_Me(t *testing.T) {
},
},
},
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{
{
Organization: "0",
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
},
}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -401,7 +432,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -410,7 +440,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
@ -420,14 +449,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
}, nil
},
@ -457,7 +478,7 @@ func TestService_Me(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}}`,
},
{
name: "New user - New users not super admin, not first user",
@ -475,6 +496,18 @@ func TestService_Me(t *testing.T) {
},
},
},
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{
{
Organization: "0",
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
},
}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -482,7 +515,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -491,7 +523,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
@ -501,14 +532,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
}, nil
},
@ -538,7 +561,7 @@ func TestService_Me(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}}`,
},
{
name: "New user - New users not super admin, first user",
@ -556,6 +579,18 @@ func TestService_Me(t *testing.T) {
},
},
},
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{
{
Organization: "0",
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
},
}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -563,7 +598,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -572,7 +606,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
@ -582,14 +615,6 @@ func TestService_Me(t *testing.T) {
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
}, nil
},
@ -619,7 +644,7 @@ func TestService_Me(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"}],"provider":"auth0","scheme":"oauth2","superAdmin":true,"links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true}}`,
},
{
name: "Error adding user",
@ -636,21 +661,24 @@ func TestService_Me(t *testing.T) {
},
},
},
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Name: "The Bad Place",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "0",
Name: "The Bad Place",
Public: true,
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Name: "The Bad Place",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "0",
Name: "The Bad Place",
Public: true,
}, nil
},
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
@ -660,14 +688,6 @@ func TestService_Me(t *testing.T) {
Name: "The Bad Place",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
}, nil
},
@ -751,6 +771,11 @@ func TestService_Me(t *testing.T) {
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
MappingsStore: &mocks.MappingsStore{
AllF: func(ctx context.Context) ([]chronograf.Mapping, error) {
return []chronograf.Mapping{}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
@ -758,7 +783,6 @@ func TestService_Me(t *testing.T) {
Name: "The Bad Place",
DefaultRole: roles.MemberRoleName,
Public: false,
Mappings: []chronograf.Mapping{},
}, nil
},
},
@ -789,101 +813,6 @@ func TestService_Me(t *testing.T) {
wantContentType: "application/json",
wantBody: `{"code":403,"message":"This organization is private. To gain access, you must be explicitly added by an administrator."}`,
},
{
name: "New user multiple mappings",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest("GET", "http://example.com/foo", nil),
},
fields: fields{
UseAuth: true,
Logger: log.New(log.DebugLevel),
ConfigStore: &mocks.ConfigStore{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
},
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
AllF: func(ctx context.Context) ([]chronograf.Organization, error) {
return []chronograf.Organization{
chronograf.Organization{
ID: "0",
Name: "The Gnarly Default",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
chronograf.Organization{
ID: "1",
Name: "another org",
DefaultRole: roles.ViewerRoleName,
Public: true,
Mappings: []chronograf.Mapping{
chronograf.Mapping{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.EditorRoleName,
},
},
},
}, nil
},
},
UsersStore: &mocks.UsersStore{
NumF: func(ctx context.Context) (int, error) {
// This function gets to verify that there is at least one first user
return 1, nil
},
GetF: func(ctx context.Context, q chronograf.UserQuery) (*chronograf.User, error) {
if q.Name == nil || q.Provider == nil || q.Scheme == nil {
return nil, fmt.Errorf("Invalid user query: missing Name, Provider, and/or Scheme")
}
return nil, chronograf.ErrUserNotFound
},
AddF: func(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
return u, nil
},
UpdateF: func(ctx context.Context, u *chronograf.User) error {
return nil
},
},
},
principal: oauth2.Principal{
Subject: "secret",
Issuer: "auth0",
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"secret","roles":[{"name":"viewer","organization":"0"},{"name":"editor","organization":"1"}],"provider":"auth0","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]},{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}],"currentOrganization":{"id":"0","name":"The Gnarly Default","defaultRole":"viewer","public":true,"mappings":[]}}`,
},
}
for _, tt := range tests {
tt.args.r = tt.args.r.WithContext(context.WithValue(context.Background(), oauth2.PrincipalKey, tt.principal))
@ -891,6 +820,7 @@ func TestService_Me(t *testing.T) {
Store: &mocks.Store{
UsersStore: tt.fields.UsersStore,
OrganizationsStore: tt.fields.OrganizationsStore,
MappingsStore: tt.fields.MappingsStore,
ConfigStore: tt.fields.ConfigStore,
},
Logger: tt.fields.Logger,
@ -981,7 +911,6 @@ func TestService_UpdateMe(t *testing.T) {
Name: "Default",
DefaultRole: roles.AdminRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -995,14 +924,12 @@ func TestService_UpdateMe(t *testing.T) {
Name: "Default",
DefaultRole: roles.AdminRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
case "1337":
return &chronograf.Organization{
ID: "1337",
Name: "The ShillBillThrilliettas",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "1337",
Name: "The ShillBillThrilliettas",
Public: true,
}, nil
}
return nil, nil
@ -1015,7 +942,7 @@ func TestService_UpdateMe(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"1337"},{"name":"admin","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"admin","public":true,"mappings":[]},{"id":"1337","name":"The ShillBillThrilliettas","public":true,"mappings":[]}],"currentOrganization":{"id":"1337","name":"The ShillBillThrilliettas","public":true,"mappings":[]}}`,
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"1337"},{"name":"admin","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"admin","public":true},{"id":"1337","name":"The ShillBillThrilliettas","public":true}],"currentOrganization":{"id":"1337","name":"The ShillBillThrilliettas","public":true}}`,
},
{
name: "Change the current User's organization",
@ -1058,7 +985,6 @@ func TestService_UpdateMe(t *testing.T) {
Name: "Default",
DefaultRole: roles.EditorRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -1068,10 +994,9 @@ func TestService_UpdateMe(t *testing.T) {
switch *q.ID {
case "1337":
return &chronograf.Organization{
ID: "1337",
Name: "The ThrillShilliettos",
Public: false,
Mappings: []chronograf.Mapping{},
ID: "1337",
Name: "The ThrillShilliettos",
Public: false,
}, nil
case "0":
return &chronograf.Organization{
@ -1079,7 +1004,6 @@ func TestService_UpdateMe(t *testing.T) {
Name: "Default",
DefaultRole: roles.EditorRoleName,
Public: true,
Mappings: []chronograf.Mapping{},
}, nil
}
return nil, nil
@ -1093,7 +1017,7 @@ func TestService_UpdateMe(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"1337"},{"name":"editor","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"editor","public":true,"mappings":[]},{"id":"1337","name":"The ThrillShilliettos","public":false,"mappings":[]}],"currentOrganization":{"id":"1337","name":"The ThrillShilliettos","public":false,"mappings":[]}}`,
wantBody: `{"name":"me","roles":[{"name":"admin","organization":"1337"},{"name":"editor","organization":"0"}],"provider":"github","scheme":"oauth2","links":{"self":"/chronograf/v1/users/0"},"organizations":[{"id":"0","name":"Default","defaultRole":"editor","public":true},{"id":"1337","name":"The ThrillShilliettos","public":false}],"currentOrganization":{"id":"1337","name":"The ThrillShilliettos","public":false}}`,
},
{
name: "Unable to find requested user in valid organization",
@ -1132,8 +1056,7 @@ func TestService_UpdateMe(t *testing.T) {
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Mappings: []chronograf.Mapping{},
ID: "0",
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
@ -1141,10 +1064,9 @@ func TestService_UpdateMe(t *testing.T) {
return nil, fmt.Errorf("Invalid organization query: missing ID")
}
return &chronograf.Organization{
ID: "1337",
Name: "The ShillBillThrilliettas",
Public: true,
Mappings: []chronograf.Mapping{},
ID: "1337",
Name: "The ShillBillThrilliettas",
Public: true,
}, nil
},
},
@ -1195,8 +1117,7 @@ func TestService_UpdateMe(t *testing.T) {
OrganizationsStore: &mocks.OrganizationsStore{
DefaultOrganizationF: func(ctx context.Context) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "0",
Mappings: []chronograf.Mapping{},
ID: "0",
}, nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {

View File

@ -118,6 +118,13 @@ func NewMux(opts MuxOpts, service Service) http.Handler {
router.PATCH("/chronograf/v1/organizations/:id", EnsureSuperAdmin(service.UpdateOrganization))
router.DELETE("/chronograf/v1/organizations/:id", EnsureSuperAdmin(service.RemoveOrganization))
// Mappings
//router.GET("/chronograf/v1/mappings", EnsureSuperAdmin(service.Mappings))
//router.POST("/chronograf/v1/mappings", EnsureSuperAdmin(service.NewMapping))
//router.PUT("/chronograf/v1/mappings/:id", EnsureSuperAdmin(service.UpdateMappings))
//router.DELETE("/chronograf/v1/mappings/:id", EnsureSuperAdmin(service.RemoveMappings))
// Sources
router.GET("/chronograf/v1/sources", EnsureViewer(service.Sources))
router.POST("/chronograf/v1/sources", EnsureEditor(service.NewSource))

View File

@ -13,10 +13,9 @@ import (
)
type organizationRequest struct {
Name string `json:"name"`
DefaultRole string `json:"defaultRole"`
Public *bool `json:"public"`
Mappings []chronograf.Mapping `json:"mappings"`
Name string `json:"name"`
DefaultRole string `json:"defaultRole"`
Public *bool `json:"public"`
}
func (r *organizationRequest) ValidCreate() error {
@ -24,36 +23,11 @@ func (r *organizationRequest) ValidCreate() error {
return fmt.Errorf("Name required on Chronograf Organization request body")
}
if len(r.Mappings) > 0 {
if err := r.ValidMappings(); err != nil {
return err
}
}
return r.ValidDefaultRole()
}
func (r *organizationRequest) ValidMappings() error {
for _, m := range r.Mappings {
if m.Provider == "" {
return fmt.Errorf("mapping must specify provider")
}
if m.Scheme == "" {
return fmt.Errorf("mapping must specify scheme")
}
if m.Group == "" {
return fmt.Errorf("mapping must specify group")
}
if m.GrantedRole == "" {
return fmt.Errorf("mapping must specify grantedRole")
}
}
return nil
}
func (r *organizationRequest) ValidUpdate() error {
if r.Name == "" && r.DefaultRole == "" && r.Public == nil && len(r.Mappings) == 0 {
if r.Name == "" && r.DefaultRole == "" && r.Public == nil {
return fmt.Errorf("No fields to update")
}
@ -61,12 +35,6 @@ func (r *organizationRequest) ValidUpdate() error {
return r.ValidDefaultRole()
}
if len(r.Mappings) > 0 {
if err := r.ValidMappings(); err != nil {
return err
}
}
return nil
}
@ -92,12 +60,6 @@ func newOrganizationResponse(o *chronograf.Organization) *organizationResponse {
if o == nil {
o = &chronograf.Organization{}
}
// This ensures that any user response with no roles returns an empty array instead of
// null when marshaled into JSON. That way, JavaScript doesn't need any guard on the
// key existing and it can simply be iterated over.
if o.Mappings == nil {
o.Mappings = []chronograf.Mapping{}
}
return &organizationResponse{
Organization: *o,
Links: selfLinks{
@ -249,10 +211,6 @@ func (s *Service) UpdateOrganization(w http.ResponseWriter, r *http.Request) {
org.Public = *req.Public
}
if req.Mappings != nil {
org.Mappings = req.Mappings
}
err = s.Store.Organizations(ctx).Update(ctx, org)
if err != nil {
Error(w, http.StatusBadRequest, err.Error(), s.Logger)

View File

@ -65,10 +65,10 @@ func TestService_OrganizationID(t *testing.T) {
id: "1337",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"links":{"self":"/chronograf/v1/organizations/1337"},"id":"1337","name":"The Good Place","public":false,"mappings":[]}`,
wantBody: `{"links":{"self":"/chronograf/v1/organizations/1337"},"id":"1337","name":"The Good Place","public":false}`,
},
{
name: "Get Single Organization - with mappings",
name: "Get Single Organization",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
@ -86,14 +86,6 @@ func TestService_OrganizationID(t *testing.T) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
default:
return nil, fmt.Errorf("Organization with ID %s not found", *q.ID)
@ -104,7 +96,7 @@ func TestService_OrganizationID(t *testing.T) {
id: "1337",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"id":"1337","name":"The Good Place","public":false,"mappings":[{"provider":"*","scheme":"*","group":"*","grantedRole":"viewer"}],"links":{"self":"/chronograf/v1/organizations/1337"}}`,
wantBody: `{"id":"1337","name":"The Good Place","public":false,"links":{"self":"/chronograf/v1/organizations/1337"}}`,
},
}
@ -186,14 +178,6 @@ func TestService_Organizations(t *testing.T) {
ID: "100",
Name: "The Bad Place",
Public: false,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
}, nil
},
@ -201,7 +185,7 @@ func TestService_Organizations(t *testing.T) {
},
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"links":{"self":"/chronograf/v1/organizations"},"organizations":[{"links":{"self":"/chronograf/v1/organizations/1337"},"mappings":[],"id":"1337","name":"The Good Place","public":false},{"links":{"self":"/chronograf/v1/organizations/100"},"id":"100","name":"The Bad Place","public":false,"mappings":[{"provider":"*","scheme":"*","group":"*","grantedRole":"viewer"}]}]}`,
wantBody: `{"links":{"self":"/chronograf/v1/organizations"},"organizations":[{"links":{"self":"/chronograf/v1/organizations/1337"},"id":"1337","name":"The Good Place","public":false},{"links":{"self":"/chronograf/v1/organizations/100"},"id":"100","name":"The Bad Place","public":false}]}`,
},
}
@ -286,243 +270,7 @@ func TestService_UpdateOrganization(t *testing.T) {
id: "1337",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"id":"1337","mappings":[],"name":"The Bad Place","defaultRole":"viewer","links":{"self":"/chronograf/v1/organizations/1337"},"public":false}`,
},
{
name: "Update Organization mappings",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
org: &organizationRequest{
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
OrganizationsStore: &mocks.OrganizationsStore{
UpdateF: func(ctx context.Context, o *chronograf.Organization) error {
return nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
},
},
},
id: "1337",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"id":"1337","public":false,"mappings":[{"provider":"*","scheme":"*","group":"*","grantedRole":"admin"}],"name":"The Good Place","defaultRole":"viewer","links":{"self":"/chronograf/v1/organizations/1337"}}`,
},
{
name: "Fail to update Organization mappings - no provider",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
org: &organizationRequest{
Mappings: []chronograf.Mapping{
{
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
OrganizationsStore: &mocks.OrganizationsStore{
UpdateF: func(ctx context.Context, o *chronograf.Organization) error {
return nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
},
},
},
id: "1337",
wantStatus: http.StatusUnprocessableEntity,
wantContentType: "application/json",
wantBody: `{"code":422,"message":"mapping must specify provider"}`,
},
{
name: "Fail to update Organization mappings - no scheme",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
org: &organizationRequest{
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
OrganizationsStore: &mocks.OrganizationsStore{
UpdateF: func(ctx context.Context, o *chronograf.Organization) error {
return nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
},
},
},
id: "1337",
wantStatus: http.StatusUnprocessableEntity,
wantContentType: "application/json",
wantBody: `{"code":422,"message":"mapping must specify scheme"}`,
},
{
name: "Fail to update Organization mappings - no group",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
org: &organizationRequest{
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
GrantedRole: roles.AdminRoleName,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
OrganizationsStore: &mocks.OrganizationsStore{
UpdateF: func(ctx context.Context, o *chronograf.Organization) error {
return nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
},
},
},
id: "1337",
wantStatus: http.StatusUnprocessableEntity,
wantContentType: "application/json",
wantBody: `{"code":422,"message":"mapping must specify group"}`,
},
{
name: "Fail to update Organization mappings - no granted role",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
org: &organizationRequest{
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
OrganizationsStore: &mocks.OrganizationsStore{
UpdateF: func(ctx context.Context, o *chronograf.Organization) error {
return nil
},
GetF: func(ctx context.Context, q chronograf.OrganizationQuery) (*chronograf.Organization, error) {
return &chronograf.Organization{
ID: "1337",
Name: "The Good Place",
DefaultRole: roles.ViewerRoleName,
Mappings: []chronograf.Mapping{
{
Provider: chronograf.MappingWildcard,
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
}, nil
},
},
},
id: "1337",
wantStatus: http.StatusUnprocessableEntity,
wantContentType: "application/json",
wantBody: `{"code":422,"message":"mapping must specify grantedRole"}`,
wantBody: `{"id":"1337","name":"The Bad Place","defaultRole":"viewer","links":{"self":"/chronograf/v1/organizations/1337"},"public":false}`,
},
{
name: "Update Organization public",
@ -556,7 +304,7 @@ func TestService_UpdateOrganization(t *testing.T) {
id: "0",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"id":"0","mappings":[],"name":"The Good Place","defaultRole":"viewer","public":false,"links":{"self":"/chronograf/v1/organizations/0"}}`,
wantBody: `{"id":"0","name":"The Good Place","defaultRole":"viewer","public":false,"links":{"self":"/chronograf/v1/organizations/0"}}`,
},
{
name: "Update Organization - nothing to update",
@ -622,7 +370,7 @@ func TestService_UpdateOrganization(t *testing.T) {
id: "1337",
wantStatus: http.StatusOK,
wantContentType: "application/json",
wantBody: `{"links":{"self":"/chronograf/v1/organizations/1337"},"mappings":[],"id":"1337","name":"The Good Place","defaultRole":"viewer","public":false}`,
wantBody: `{"links":{"self":"/chronograf/v1/organizations/1337"},"id":"1337","name":"The Good Place","defaultRole":"viewer","public":false}`,
},
{
name: "Update Organization - invalid update",
@ -865,7 +613,7 @@ func TestService_NewOrganization(t *testing.T) {
},
wantStatus: http.StatusCreated,
wantContentType: "application/json",
wantBody: `{"id":"1337","mappings":[],"public":false,"name":"The Good Place","links":{"self":"/chronograf/v1/organizations/1337"}}`,
wantBody: `{"id":"1337","public":false,"name":"The Good Place","links":{"self":"/chronograf/v1/organizations/1337"}}`,
},
{
name: "Fail to create Organization - no org name",
@ -906,54 +654,6 @@ func TestService_NewOrganization(t *testing.T) {
wantContentType: "application/json",
wantBody: `{"code":422,"message":"Name required on Chronograf Organization request body"}`,
},
{
name: "Fail to create Organization - mappings missing provider",
args: args{
w: httptest.NewRecorder(),
r: httptest.NewRequest(
"GET",
"http://any.url", // can be any valid URL as we are bypassing mux
nil,
),
user: &chronograf.User{
ID: 1,
Name: "bobetta",
Provider: "github",
Scheme: "oauth2",
},
org: &organizationRequest{
Name: "The Good Place",
Mappings: []chronograf.Mapping{
{
Scheme: chronograf.MappingWildcard,
Group: chronograf.MappingWildcard,
GrantedRole: roles.ViewerRoleName,
},
},
},
},
fields: fields{
Logger: log.New(log.DebugLevel),
UsersStore: &mocks.UsersStore{
AddF: func(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
return &chronograf.User{
ID: 1,
Name: "bobetta",
Provider: "github",
Scheme: "oauth2",
}, nil
},
},
OrganizationsStore: &mocks.OrganizationsStore{
AddF: func(ctx context.Context, o *chronograf.Organization) (*chronograf.Organization, error) {
return nil, nil
},
},
},
wantStatus: http.StatusUnprocessableEntity,
wantContentType: "application/json",
wantBody: `{"code":422,"message":"mapping must specify provider"}`,
},
{
name: "Create Organization - no user on context",
args: args{

View File

@ -484,6 +484,7 @@ func openService(ctx context.Context, buildInfo chronograf.BuildInfo, boltPath s
OrganizationsStore: organizations,
UsersStore: db.UsersStore,
ConfigStore: db.ConfigStore,
MappingsStore: db.MappingsStore,
},
Logger: logger,
UseAuth: useAuth,

View File

@ -88,6 +88,7 @@ type DataStore interface {
Layouts(ctx context.Context) chronograf.LayoutsStore
Users(ctx context.Context) chronograf.UsersStore
Organizations(ctx context.Context) chronograf.OrganizationsStore
Mappings(ctx context.Context) chronograf.MappingsStore
Dashboards(ctx context.Context) chronograf.DashboardsStore
Config(ctx context.Context) chronograf.ConfigStore
}
@ -102,6 +103,7 @@ type Store struct {
LayoutsStore chronograf.LayoutsStore
UsersStore chronograf.UsersStore
DashboardsStore chronograf.DashboardsStore
MappingsStore chronograf.MappingsStore
OrganizationsStore chronograf.OrganizationsStore
ConfigStore chronograf.ConfigStore
}
@ -191,3 +193,14 @@ func (s *Store) Config(ctx context.Context) chronograf.ConfigStore {
}
return &noop.ConfigStore{}
}
// Mappings returns the underlying MappingsStore.
func (s *Store) Mappings(ctx context.Context) chronograf.MappingsStore {
if isServer := hasServerContext(ctx); isServer {
return s.MappingsStore
}
if isSuperAdmin := hasSuperAdminContext(ctx); isSuperAdmin {
return s.MappingsStore
}
return &noop.MappingsStore{}
}