From 6fda0401ef2ea6950f16d30634ff05d08626464a Mon Sep 17 00:00:00 2001 From: Asim Aslam Date: Mon, 3 May 2021 14:36:29 +0100 Subject: [PATCH] Make invites use store (#92) --- go.mod | 2 +- go.sum | 2 + invites/handler/invites.go | 247 ++++++++++++++++++++++++------ invites/handler/invites_test.go | 55 +++---- invites/main.go | 22 +-- invites/proto/invites.pb.go | 171 +++++++++------------ invites/proto/invites.pb.micro.go | 1 - invites/proto/invites.proto | 9 +- pkg/tenant/tenant.go | 10 ++ 9 files changed, 308 insertions(+), 211 deletions(-) diff --git a/go.mod b/go.mod index 153033f..4d7793e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/hailocab/go-geoindex v0.0.0-20160127134810-64631bfe9711 github.com/jackc/pgx/v4 v4.10.1 github.com/micro/dev v0.0.0-20201117163752-d3cfc9788dfa - github.com/micro/micro/v3 v3.2.1-0.20210416134206-20d3a6b03014 + github.com/micro/micro/v3 v3.2.2-0.20210502173659-359ab425002e github.com/miekg/dns v1.1.31 // indirect github.com/nats-io/nats-streaming-server v0.21.1 github.com/paulmach/go.geo v0.0.0-20180829195134-22b514266d33 diff --git a/go.sum b/go.sum index e5c9e7e..ebbd7ad 100644 --- a/go.sum +++ b/go.sum @@ -400,6 +400,8 @@ github.com/micro/dev v0.0.0-20201117163752-d3cfc9788dfa/go.mod h1:j/8E+ezN/ij7a9 github.com/micro/micro/v3 v3.0.0-beta.6.0.20201016094841-ca8ffd563b2b/go.mod h1:RPJTp9meQAppzW/9jgQtfJmPpRJAySVPbz9uur4B3Ko= github.com/micro/micro/v3 v3.2.1-0.20210416134206-20d3a6b03014 h1:6yuX6VfXT8XZCK9PrFeh4KN/ZG7iaQeMbhl593C9SCE= github.com/micro/micro/v3 v3.2.1-0.20210416134206-20d3a6b03014/go.mod h1:UqfLMsy88SNqc31m7tNMQb6xLNGtsKkjJJFp3iHFXfs= +github.com/micro/micro/v3 v3.2.2-0.20210502173659-359ab425002e h1:o58+WWFR5l85vktSL/mQQFrGwG88PPyeuGlaQF348yU= +github.com/micro/micro/v3 v3.2.2-0.20210502173659-359ab425002e/go.mod h1:3jH/R5iGtpMyeKH09iHt3KIw8gSFN7aW3W4iGOWUucE= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= diff --git a/invites/handler/invites.go b/invites/handler/invites.go index 70b49f2..d1554e8 100644 --- a/invites/handler/invites.go +++ b/invites/handler/invites.go @@ -2,6 +2,8 @@ package handler import ( "context" + "encoding/json" + "fmt" "math/rand" "regexp" "strconv" @@ -11,9 +13,9 @@ import ( "github.com/micro/micro/v3/service/auth" "github.com/micro/micro/v3/service/errors" "github.com/micro/micro/v3/service/logger" + "github.com/micro/micro/v3/service/store" pb "github.com/micro/services/invites/proto" - gorm2 "github.com/micro/services/pkg/gorm" - "gorm.io/gorm" + "github.com/micro/services/pkg/tenant" ) var ( @@ -30,9 +32,9 @@ var ( type Invite struct { ID string - Email string `gorm:"uniqueIndex:group_email"` - GroupID string `gorm:"uniqueIndex:group_email"` - Code string `gorm:"uniqueIndex"` + Email string + GroupID string + Code string } func (i *Invite) Serialize() *pb.Invite { @@ -44,10 +46,43 @@ func (i *Invite) Serialize() *pb.Invite { } } -type Invites struct { - gorm2.Helper +func (i *Invite) Key(ctx context.Context) string { + key := fmt.Sprintf("invite:%s:%s", i.ID, i.Code) + + t, ok := tenant.FromContext(ctx) + if !ok { + return key + } + + return fmt.Sprintf("%s/%s", t, key) } +func (i *Invite) GroupKey(ctx context.Context) string { + key := fmt.Sprintf("group:%s:%s", i.GroupID, i.Email) + + t, ok := tenant.FromContext(ctx) + if !ok { + return key + } + + return fmt.Sprintf("%s/%s", t, key) +} + +func (i *Invite) Marshal() []byte { + b, _ := json.Marshal(i) + return b +} + +func (i *Invite) Unmarshal(b []byte) error { + return json.Unmarshal(b, &i) +} + +type Invites struct{} + +// schema +// Read: id/code +// List: group/email + // Create an invite func (i *Invites) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { _, ok := auth.AccountFromContext(ctx) @@ -72,12 +107,22 @@ func (i *Invites) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.Cre GroupID: req.GroupId, Email: strings.ToLower(req.Email), } - db, err := i.GetDBConn(ctx) - if err != nil { - logger.Errorf("Error connecting to DB: %v", err) - return errors.InternalServerError("DB_ERROR", "Error connecting to DB") + + // id/val + key := invite.Key(ctx) + // get group key + gkey := invite.GroupKey(ctx) + + // TODO: Use the micro/micro/v3/service/sync interface to lock + + // write the first record + if err := store.Write(store.NewRecord(key, invite)); err != nil { + logger.Errorf("Error writing to the store: %v", err) + return errors.InternalServerError("DATABASE_ERROR", "Error connecting to the database") } - if err := db.Create(invite).Error; err != nil && !strings.Contains(err.Error(), "group_email") { + + // write the group record + if err := store.Write(store.NewRecord(gkey, invite)); err != nil { logger.Errorf("Error writing to the store: %v", err) return errors.InternalServerError("DATABASE_ERROR", "Error connecting to the database") } @@ -94,29 +139,75 @@ func (i *Invites) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadRes errors.Unauthorized("UNAUTHORIZED", "Unauthorized") } // validate the request - var query Invite - if req.Id != nil { - query.ID = req.Id.Value - } else if req.Code != nil { - query.Code = req.Code.Value - } else { + if len(req.Id) == 0 && len(req.Code) == 0 { return ErrMissingIDAndCode } - db, err := i.GetDBConn(ctx) - if err != nil { - logger.Errorf("Error connecting to DB: %v", err) - return errors.InternalServerError("DB_ERROR", "Error connecting to DB") + var recs []*store.Record + var err error + + // create a pseudo invite + invite := &Invite{ + ID: req.Id, + Code: req.Code, } - // query the database - var invite Invite - if err := db.Where(&query).First(&invite).Error; err == gorm.ErrRecordNotFound { + + if len(req.Id) > 0 && len(req.Code) > 0 { + recs, err = store.Read(invite.Key(ctx), store.ReadLimit(1)) + } else if len(req.Id) > 0 { + recs, err = store.Read(invite.Key(ctx), store.ReadLimit(1), store.ReadPrefix()) + } else if len(req.Code) > 0 { + // create a code suffix key + key := ":" + req.Code + // read all the keys with the given code + // TODO: potential race where if the code is not random + // we read it for the wrong user e.g if two tenants generate the same code + r, lerr := store.Read(key, store.ReadLimit(1), store.ReadSuffix()) + + // now scan for the prefix + prefix := "invite:" + + // additional prefix for the tenant + if t, ok := tenant.FromContext(ctx); ok { + prefix = t + "/" + prefix + } + + // scan for the key we're looking for + for _, rec := range r { + // skip the missing prefix + if !strings.HasPrefix(rec.Key, prefix) { + continue + } + + // skip missing suffix + if !strings.HasSuffix(rec.Key, key) { + continue + } + + // save the record + recs = append(recs, rec) + break + } + + // set the error + // TODO: maybe just process this + err = lerr + } + + // check if there are any records + if err == store.ErrNotFound || len(recs) == 0 { return ErrInviteNotFound - } else if err != nil { + } + + // check the error + if err != nil { logger.Errorf("Error reading from the store: %v", err) return errors.InternalServerError("DATABASE_ERROR", "Error connecting to the database") } + // unmarshal the invite + invite.Unmarshal(recs[0].Value) + // serialize the response rsp.Invite = invite.Serialize() return nil @@ -129,36 +220,77 @@ func (i *Invites) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListRes errors.Unauthorized("UNAUTHORIZED", "Unauthorized") } // validate the request - if req.Email == nil && req.GroupId == nil { + if len(req.Email) == 0 && len(req.GroupId) == 0 { return ErrMissingGroupIDAndEmail } - // construct the query - var query Invite - if req.GroupId != nil { - query.GroupID = req.GroupId.Value - } - if req.Email != nil { - query.Email = strings.ToLower(req.Email.Value) + invite := &Invite{ + GroupID: req.GroupId, + Email: req.Email, } - db, err := i.GetDBConn(ctx) - if err != nil { - logger.Errorf("Error connecting to DB: %v", err) - return errors.InternalServerError("DB_ERROR", "Error connecting to DB") + var recs []*store.Record + var err error + + if len(invite.GroupID) > 0 && len(invite.Email) > 0 { + key := invite.GroupKey(ctx) + recs, err = store.Read(key, store.ReadLimit(1)) + } else if len(invite.GroupID) > 0 { + key := invite.GroupKey(ctx) + recs, err = store.Read(key, store.ReadPrefix()) + } else if len(invite.Email) > 0 { + // create a email suffix key + key := ":" + invite.Email + // read all the keys with the given code + r, lerr := store.Read(key, store.ReadSuffix()) + + // now scan for the prefix + prefix := "group:" + + // additional prefix for the tenant + if t, ok := tenant.FromContext(ctx); ok { + prefix = t + "/" + prefix + } + + // scan for the key we're looking for + for _, rec := range r { + // skip the missing prefix + if !strings.HasPrefix(rec.Key, prefix) { + continue + } + + // skip missing suffix + if !strings.HasSuffix(rec.Key, key) { + continue + } + + // save the record + recs = append(recs, rec) + } + + // set the error + // TODO: maybe just process this + err = lerr } - // query the database - var invites []Invite - if err := db.Where(&query).Find(&invites).Error; err != nil { + + // no records found + if err == store.ErrNotFound { + return nil + } + + // check the error + if err != nil { logger.Errorf("Error reading from the store: %v", err) return errors.InternalServerError("DATABASE_ERROR", "Error connecting to the database") } - // serialize the response - rsp.Invites = make([]*pb.Invite, len(invites)) - for i, inv := range invites { - rsp.Invites[i] = inv.Serialize() + // return response + for _, rec := range recs { + invite := new(Invite) + invite.Unmarshal(rec.Value) + rsp.Invites = append(rsp.Invites, invite.Serialize()) } + return nil } @@ -173,17 +305,30 @@ func (i *Invites) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.Del return ErrMissingID } - db, err := i.GetDBConn(ctx) - if err != nil { + invite := &Invite{ID: req.Id} + key := invite.Key(ctx) + + // check for the existing invite value + recs, err := store.Read(key, store.ReadLimit(1), store.ReadPrefix()) + if err == store.ErrNotFound || len(recs) == 0 { + return nil + } else if err != nil { logger.Errorf("Error connecting to DB: %v", err) return errors.InternalServerError("DB_ERROR", "Error connecting to DB") } - // delete from the database - if err := db.Where(&Invite{ID: req.Id}).Delete(&Invite{}).Error; err != nil { - logger.Errorf("Error deleting from the store: %v", err) - return errors.InternalServerError("DATABASE_ERROR", "Error connecting to the database") + + // unmarshal the existing invite + invite.Unmarshal(recs[0].Value) + if invite.ID != req.Id { + return nil } + // delete the record by id + store.Delete(invite.Key(ctx)) + + // delete the record by group id + store.Delete(invite.GroupKey(ctx)) + return nil } diff --git a/invites/handler/invites_test.go b/invites/handler/invites_test.go index 6a869f3..dc62ed8 100644 --- a/invites/handler/invites_test.go +++ b/invites/handler/invites_test.go @@ -2,38 +2,21 @@ package handler_test import ( "context" - "database/sql" - "os" "testing" "github.com/micro/micro/v3/service/auth" + "github.com/micro/micro/v3/service/store" + "github.com/micro/micro/v3/service/store/memory" "github.com/micro/services/invites/handler" pb "github.com/micro/services/invites/proto" - "google.golang.org/protobuf/types/known/wrapperspb" "github.com/google/uuid" "github.com/stretchr/testify/assert" ) func testHandler(t *testing.T) *handler.Invites { - // connect to the database - addr := os.Getenv("POSTGRES_URL") - if len(addr) == 0 { - addr = "postgresql://postgres@localhost:5432/postgres?sslmode=disable" - } - sqlDB, err := sql.Open("pgx", addr) - if err != nil { - t.Fatalf("Failed to open connection to DB %s", err) - } - - // clean any data from a previous run - if _, err := sqlDB.Exec(`DROP TABLE IF EXISTS "micro_someID_invites" CASCADE`); err != nil { - t.Fatalf("Error cleaning database: %v", err) - } - - h := &handler.Invites{} - h.DBConn(sqlDB).Migrations(&handler.Invite{}) - return h + store.DefaultStore = memory.NewStore() + return &handler.Invites{} } func TestCreate(t *testing.T) { @@ -112,8 +95,8 @@ func TestRead(t *testing.T) { tt := []struct { Name string - ID *wrapperspb.StringValue - Code *wrapperspb.StringValue + ID string + Code string Error error Invite *pb.Invite }{ @@ -123,22 +106,22 @@ func TestRead(t *testing.T) { }, { Name: "NotFoundByID", - ID: &wrapperspb.StringValue{Value: uuid.New().String()}, + ID: uuid.New().String(), Error: handler.ErrInviteNotFound, }, { Name: "NotFoundByCode", - Code: &wrapperspb.StringValue{Value: "12345678"}, + Code: "12345678", Error: handler.ErrInviteNotFound, }, { Name: "ValidID", - ID: &wrapperspb.StringValue{Value: cRsp.Invite.Id}, + ID: cRsp.Invite.Id, Invite: cRsp.Invite, }, { Name: "ValidCode", - Code: &wrapperspb.StringValue{Value: cRsp.Invite.Code}, + Code: cRsp.Invite.Code, Invite: cRsp.Invite, }, } @@ -172,8 +155,8 @@ func TestList(t *testing.T) { tt := []struct { Name string - GroupID *wrapperspb.StringValue - Email *wrapperspb.StringValue + GroupID string + Email string Error error Invite *pb.Invite }{ @@ -183,26 +166,26 @@ func TestList(t *testing.T) { }, { Name: "NoResultsForEmail", - Email: &wrapperspb.StringValue{Value: "foo@bar.com"}, + Email: "foo@bar.com", }, { Name: "NoResultsForGroupID", - GroupID: &wrapperspb.StringValue{Value: uuid.New().String()}, + GroupID: uuid.New().String(), }, { Name: "ValidGroupID", - GroupID: &wrapperspb.StringValue{Value: cRsp.Invite.GroupId}, + GroupID: cRsp.Invite.GroupId, Invite: cRsp.Invite, }, { Name: "ValidEmail", - Email: &wrapperspb.StringValue{Value: cRsp.Invite.Email}, + Email: cRsp.Invite.Email, Invite: cRsp.Invite, }, { Name: "EmailAndGroupID", - Email: &wrapperspb.StringValue{Value: cRsp.Invite.Email}, - GroupID: &wrapperspb.StringValue{Value: uuid.New().String()}, + Email: cRsp.Invite.Email, + GroupID: uuid.New().String(), }, } @@ -246,7 +229,7 @@ func TestDelete(t *testing.T) { err := h.Delete(microAccountCtx(), &pb.DeleteRequest{Id: cRsp.Invite.Id}, &pb.DeleteResponse{}) assert.NoError(t, err) - err = h.Read(microAccountCtx(), &pb.ReadRequest{Id: &wrapperspb.StringValue{Value: cRsp.Invite.Id}}, &pb.ReadResponse{}) + err = h.Read(microAccountCtx(), &pb.ReadRequest{Id: cRsp.Invite.Id}, &pb.ReadResponse{}) assert.Equal(t, handler.ErrInviteNotFound, err) }) diff --git a/invites/main.go b/invites/main.go index 53bb46e..967b3c0 100644 --- a/invites/main.go +++ b/invites/main.go @@ -1,20 +1,13 @@ package main import ( - "database/sql" - "github.com/micro/services/invites/handler" pb "github.com/micro/services/invites/proto" "github.com/micro/micro/v3/service" - "github.com/micro/micro/v3/service/config" "github.com/micro/micro/v3/service/logger" - - _ "github.com/jackc/pgx/v4/stdlib" ) -var dbAddress = "postgresql://postgres:postgres@localhost:5432/invites?sslmode=disable" - func main() { // Create service srv := service.New( @@ -22,21 +15,8 @@ func main() { service.Version("latest"), ) - // Connect to the database - cfg, err := config.Get("invites.database") - if err != nil { - logger.Fatalf("Error loading config: %v", err) - } - addr := cfg.String(dbAddress) - sqlDB, err := sql.Open("pgx", addr) - if err != nil { - logger.Fatalf("Failed to open connection to DB %s", err) - } - h := &handler.Invites{} - h.DBConn(sqlDB).Migrations(&handler.Invite{}) - // Register handler - pb.RegisterInvitesHandler(srv.Server(), h) + pb.RegisterInvitesHandler(srv.Server(), new(handler.Invites)) // Run service if err := srv.Run(); err != nil { diff --git a/invites/proto/invites.pb.go b/invites/proto/invites.pb.go index 4a4773d..c9598e3 100644 --- a/invites/proto/invites.pb.go +++ b/invites/proto/invites.pb.go @@ -1,16 +1,14 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 -// protoc v3.15.5 +// protoc-gen-go v1.26.0 +// protoc v3.15.6 // source: proto/invites.proto package invites import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -22,10 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type Invite struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -204,8 +198,8 @@ type ReadRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id *wrapperspb.StringValue `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Code *wrapperspb.StringValue `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` } func (x *ReadRequest) Reset() { @@ -240,18 +234,18 @@ func (*ReadRequest) Descriptor() ([]byte, []int) { return file_proto_invites_proto_rawDescGZIP(), []int{3} } -func (x *ReadRequest) GetId() *wrapperspb.StringValue { +func (x *ReadRequest) GetId() string { if x != nil { return x.Id } - return nil + return "" } -func (x *ReadRequest) GetCode() *wrapperspb.StringValue { +func (x *ReadRequest) GetCode() string { if x != nil { return x.Code } - return nil + return "" } type ReadResponse struct { @@ -306,8 +300,8 @@ type ListRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - GroupId *wrapperspb.StringValue `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - Email *wrapperspb.StringValue `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + GroupId string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` } func (x *ListRequest) Reset() { @@ -342,18 +336,18 @@ func (*ListRequest) Descriptor() ([]byte, []int) { return file_proto_invites_proto_rawDescGZIP(), []int{5} } -func (x *ListRequest) GetGroupId() *wrapperspb.StringValue { +func (x *ListRequest) GetGroupId() string { if x != nil { return x.GroupId } - return nil + return "" } -func (x *ListRequest) GetEmail() *wrapperspb.StringValue { +func (x *ListRequest) GetEmail() string { if x != nil { return x.Email } - return nil + return "" } type ListResponse struct { @@ -492,9 +486,7 @@ var File_proto_invites_proto protoreflect.FileDescriptor var file_proto_invites_proto_rawDesc = []byte{ 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x1a, 0x1e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, - 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, @@ -508,49 +500,41 @@ var file_proto_invites_proto_rawDesc = []byte{ 0x39, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x22, 0x6d, 0x0a, 0x0b, 0x52, 0x65, - 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x37, 0x0a, 0x0c, 0x52, 0x65, 0x61, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x69, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x22, 0x7a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x37, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x05, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x39, - 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, - 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x52, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe9, 0x01, 0x0a, - 0x07, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x12, 0x16, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x14, 0x2e, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x14, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, - 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0f, 0x5a, 0x0d, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x3b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x74, 0x65, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x22, 0x31, 0x0a, 0x0b, 0x52, 0x65, + 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x37, 0x0a, + 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, + 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x06, + 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x22, 0x3e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x39, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x73, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe9, 0x01, 0x0a, 0x07, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, + 0x12, 0x39, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x69, 0x6e, 0x76, + 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x52, + 0x65, 0x61, 0x64, 0x12, 0x14, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, + 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x33, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, + 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x16, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -567,38 +551,33 @@ func file_proto_invites_proto_rawDescGZIP() []byte { var file_proto_invites_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_proto_invites_proto_goTypes = []interface{}{ - (*Invite)(nil), // 0: invites.Invite - (*CreateRequest)(nil), // 1: invites.CreateRequest - (*CreateResponse)(nil), // 2: invites.CreateResponse - (*ReadRequest)(nil), // 3: invites.ReadRequest - (*ReadResponse)(nil), // 4: invites.ReadResponse - (*ListRequest)(nil), // 5: invites.ListRequest - (*ListResponse)(nil), // 6: invites.ListResponse - (*DeleteRequest)(nil), // 7: invites.DeleteRequest - (*DeleteResponse)(nil), // 8: invites.DeleteResponse - (*wrapperspb.StringValue)(nil), // 9: google.protobuf.StringValue + (*Invite)(nil), // 0: invites.Invite + (*CreateRequest)(nil), // 1: invites.CreateRequest + (*CreateResponse)(nil), // 2: invites.CreateResponse + (*ReadRequest)(nil), // 3: invites.ReadRequest + (*ReadResponse)(nil), // 4: invites.ReadResponse + (*ListRequest)(nil), // 5: invites.ListRequest + (*ListResponse)(nil), // 6: invites.ListResponse + (*DeleteRequest)(nil), // 7: invites.DeleteRequest + (*DeleteResponse)(nil), // 8: invites.DeleteResponse } var file_proto_invites_proto_depIdxs = []int32{ - 0, // 0: invites.CreateResponse.invite:type_name -> invites.Invite - 9, // 1: invites.ReadRequest.id:type_name -> google.protobuf.StringValue - 9, // 2: invites.ReadRequest.code:type_name -> google.protobuf.StringValue - 0, // 3: invites.ReadResponse.invite:type_name -> invites.Invite - 9, // 4: invites.ListRequest.group_id:type_name -> google.protobuf.StringValue - 9, // 5: invites.ListRequest.email:type_name -> google.protobuf.StringValue - 0, // 6: invites.ListResponse.invites:type_name -> invites.Invite - 1, // 7: invites.Invites.Create:input_type -> invites.CreateRequest - 3, // 8: invites.Invites.Read:input_type -> invites.ReadRequest - 5, // 9: invites.Invites.List:input_type -> invites.ListRequest - 7, // 10: invites.Invites.Delete:input_type -> invites.DeleteRequest - 2, // 11: invites.Invites.Create:output_type -> invites.CreateResponse - 4, // 12: invites.Invites.Read:output_type -> invites.ReadResponse - 6, // 13: invites.Invites.List:output_type -> invites.ListResponse - 8, // 14: invites.Invites.Delete:output_type -> invites.DeleteResponse - 11, // [11:15] is the sub-list for method output_type - 7, // [7:11] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 0, // 0: invites.CreateResponse.invite:type_name -> invites.Invite + 0, // 1: invites.ReadResponse.invite:type_name -> invites.Invite + 0, // 2: invites.ListResponse.invites:type_name -> invites.Invite + 1, // 3: invites.Invites.Create:input_type -> invites.CreateRequest + 3, // 4: invites.Invites.Read:input_type -> invites.ReadRequest + 5, // 5: invites.Invites.List:input_type -> invites.ListRequest + 7, // 6: invites.Invites.Delete:input_type -> invites.DeleteRequest + 2, // 7: invites.Invites.Create:output_type -> invites.CreateResponse + 4, // 8: invites.Invites.Read:output_type -> invites.ReadResponse + 6, // 9: invites.Invites.List:output_type -> invites.ListResponse + 8, // 10: invites.Invites.Delete:output_type -> invites.DeleteResponse + 7, // [7:11] is the sub-list for method output_type + 3, // [3:7] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_proto_invites_proto_init() } diff --git a/invites/proto/invites.pb.micro.go b/invites/proto/invites.pb.micro.go index 7fc5bab..2590923 100644 --- a/invites/proto/invites.pb.micro.go +++ b/invites/proto/invites.pb.micro.go @@ -6,7 +6,6 @@ package invites import ( fmt "fmt" proto "github.com/golang/protobuf/proto" - _ "google.golang.org/protobuf/types/known/wrapperspb" math "math" ) diff --git a/invites/proto/invites.proto b/invites/proto/invites.proto index d56bd83..40dd1c9 100644 --- a/invites/proto/invites.proto +++ b/invites/proto/invites.proto @@ -2,7 +2,6 @@ syntax = "proto3"; package invites; option go_package = "./proto;invites"; -import "google/protobuf/wrappers.proto"; service Invites { // Create an invite @@ -32,8 +31,8 @@ message CreateResponse { } message ReadRequest { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue code = 2; + string id = 1; + string code = 2; } message ReadResponse { @@ -41,8 +40,8 @@ message ReadResponse { } message ListRequest { - google.protobuf.StringValue group_id = 1; - google.protobuf.StringValue email = 2; + string group_id = 1; + string email = 2; } message ListResponse { diff --git a/pkg/tenant/tenant.go b/pkg/tenant/tenant.go index 3d8b3c4..46cb708 100644 --- a/pkg/tenant/tenant.go +++ b/pkg/tenant/tenant.go @@ -25,3 +25,13 @@ func FromAccount(acc *auth.Account) string { } return fmt.Sprintf("%s/%s", acc.Issuer, owner) } + +// CreateKey generated a unique key for a resource +func CreateKey(ctx context.Context, key string) string { + t, ok := FromContext(ctx) + if !ok { + return key + } + // return a tenant prefixed key e.g micro/asim/foobar + return fmt.Sprintf("%s/%s", t, key) +}